mirror of
https://github.com/postgres/postgres.git
synced 2025-07-20 05:03:10 +03:00
Add support for multi-row VALUES clauses as part of INSERT statements
(e.g. "INSERT ... VALUES (...), (...), ...") and elsewhere as allowed by the spec. (e.g. similar to a FROM clause subselect). initdb required. Joe Conway and Tom Lane.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.149 2006/07/14 14:52:20 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.150 2006/08/02 01:59:45 joe Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -48,6 +48,8 @@ static void set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
Index rti, RangeTblEntry *rte);
|
||||
static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
|
||||
static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed,
|
||||
List *initial_rels);
|
||||
@ -170,6 +172,11 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti)
|
||||
/* RangeFunction --- generate a separate plan for it */
|
||||
set_function_pathlist(root, rel, rte);
|
||||
}
|
||||
else if (rel->rtekind == RTE_VALUES)
|
||||
{
|
||||
/* Values list --- generate a separate plan for it */
|
||||
set_values_pathlist(root, rel, rte);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Plain relation */
|
||||
@ -537,6 +544,23 @@ set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
|
||||
set_cheapest(rel);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_values_pathlist
|
||||
* Build the (single) access path for a VALUES RTE
|
||||
*/
|
||||
static void
|
||||
set_values_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
|
||||
{
|
||||
/* Mark rel with estimated output rows, width, etc */
|
||||
set_values_size_estimates(root, rel);
|
||||
|
||||
/* Generate appropriate path */
|
||||
add_path(rel, create_valuesscan_path(root, rel));
|
||||
|
||||
/* Select cheapest path (pretty easy in this case...) */
|
||||
set_cheapest(rel);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_rel_from_joinlist
|
||||
* Build access paths using a "joinlist" to guide the join path search.
|
||||
|
@ -54,7 +54,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.164 2006/07/26 11:35:56 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.165 2006/08/02 01:59:45 joe Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -774,6 +774,36 @@ cost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel)
|
||||
path->total_cost = startup_cost + run_cost;
|
||||
}
|
||||
|
||||
/*
|
||||
* cost_valuesscan
|
||||
* Determines and returns the cost of scanning a VALUES RTE.
|
||||
*/
|
||||
void
|
||||
cost_valuesscan(Path *path, PlannerInfo *root, RelOptInfo *baserel)
|
||||
{
|
||||
Cost startup_cost = 0;
|
||||
Cost run_cost = 0;
|
||||
Cost cpu_per_tuple;
|
||||
|
||||
/* Should only be applied to base relations that are values lists */
|
||||
Assert(baserel->relid > 0);
|
||||
Assert(baserel->rtekind == RTE_VALUES);
|
||||
|
||||
/*
|
||||
* For now, estimate list evaluation cost at one operator eval per
|
||||
* list (probably pretty bogus, but is it worth being smarter?)
|
||||
*/
|
||||
cpu_per_tuple = cpu_operator_cost;
|
||||
|
||||
/* Add scanning CPU costs */
|
||||
startup_cost += baserel->baserestrictcost.startup;
|
||||
cpu_per_tuple += cpu_tuple_cost + baserel->baserestrictcost.per_tuple;
|
||||
run_cost += cpu_per_tuple * baserel->tuples;
|
||||
|
||||
path->startup_cost = startup_cost;
|
||||
path->total_cost = startup_cost + run_cost;
|
||||
}
|
||||
|
||||
/*
|
||||
* cost_sort
|
||||
* Determines and returns the cost of sorting a relation, including
|
||||
@ -2023,6 +2053,37 @@ set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel)
|
||||
set_baserel_size_estimates(root, rel);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_values_size_estimates
|
||||
* Set the size estimates for a base relation that is a values list.
|
||||
*
|
||||
* The rel's targetlist and restrictinfo list must have been constructed
|
||||
* already.
|
||||
*
|
||||
* We set the same fields as set_baserel_size_estimates.
|
||||
*/
|
||||
void
|
||||
set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel)
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
|
||||
/* Should only be applied to base relations that are values lists */
|
||||
Assert(rel->relid > 0);
|
||||
rte = rt_fetch(rel->relid, root->parse->rtable);
|
||||
Assert(rte->rtekind == RTE_VALUES);
|
||||
|
||||
/*
|
||||
* Estimate number of rows the values list will return.
|
||||
* We know this precisely based on the list length (well,
|
||||
* barring set-returning functions in list items, but that's
|
||||
* a refinement not catered for anywhere else either).
|
||||
*/
|
||||
rel->tuples = list_length(rte->values_lists);
|
||||
|
||||
/* Now estimate number of output rows, etc */
|
||||
set_baserel_size_estimates(root, rel);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set_rel_width
|
||||
|
Reference in New Issue
Block a user