mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Teach the planner to remove SubqueryScan nodes from the plan if they
aren't doing anything useful (ie, neither selection nor projection). Also, extend to SubqueryScan the hacks already in place to avoid unnecessary ExecProject calls when the result would just be the same tuple the subquery already delivered. This saves some overhead in UNION and other set operations, as well as avoiding overhead for unflatten-able subqueries. Per example from Sokolov Yura.
This commit is contained in:
@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.120 2005/04/06 16:34:06 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.121 2005/05/22 22:30:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -61,6 +61,7 @@ static List *recurse_union_children(Node *setOp, Query *parse,
|
||||
SetOperationStmt *top_union,
|
||||
List *refnames_tlist);
|
||||
static List *generate_setop_tlist(List *colTypes, int flag,
|
||||
Index varno,
|
||||
bool hack_constants,
|
||||
List *input_tlist,
|
||||
List *refnames_tlist);
|
||||
@ -119,8 +120,8 @@ plan_set_operations(Query *parse, List **sortClauses)
|
||||
/*
|
||||
* Recurse on setOperations tree to generate plans for set ops. The
|
||||
* final output plan should have just the column types shown as the
|
||||
* output from the top-level node, plus possibly a resjunk working
|
||||
* column (we can rely on upper-level nodes to deal with that).
|
||||
* output from the top-level node, plus possibly resjunk working
|
||||
* columns (we can rely on upper-level nodes to deal with that).
|
||||
*/
|
||||
return recurse_set_operations((Node *) topop, parse,
|
||||
topop->colTypes, true, -1,
|
||||
@ -163,7 +164,9 @@ recurse_set_operations(Node *setOp, Query *parse,
|
||||
* Add a SubqueryScan with the caller-requested targetlist
|
||||
*/
|
||||
plan = (Plan *)
|
||||
make_subqueryscan(generate_setop_tlist(colTypes, flag, true,
|
||||
make_subqueryscan(generate_setop_tlist(colTypes, flag,
|
||||
rtr->rtindex,
|
||||
true,
|
||||
subplan->targetlist,
|
||||
refnames_tlist),
|
||||
NIL,
|
||||
@ -202,13 +205,15 @@ recurse_set_operations(Node *setOp, Query *parse,
|
||||
* the subplan. However, since the subplan was generated by
|
||||
* generate_union_plan() or generate_nonunion_plan(), and hence
|
||||
* its tlist was generated by generate_append_tlist(), this will
|
||||
* work.
|
||||
* work. We just tell generate_setop_tlist() to use varno 0.
|
||||
*/
|
||||
if (flag >= 0 ||
|
||||
!tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
|
||||
{
|
||||
plan = (Plan *)
|
||||
make_result(generate_setop_tlist(colTypes, flag, false,
|
||||
make_result(generate_setop_tlist(colTypes, flag,
|
||||
0,
|
||||
false,
|
||||
plan->targetlist,
|
||||
refnames_tlist),
|
||||
NULL,
|
||||
@ -415,12 +420,14 @@ recurse_union_children(Node *setOp, Query *parse,
|
||||
*
|
||||
* colTypes: column datatypes for non-junk columns
|
||||
* flag: -1 if no flag column needed, 0 or 1 to create a const flag column
|
||||
* varno: varno to use in generated Vars
|
||||
* hack_constants: true to copy up constants (see comments in code)
|
||||
* input_tlist: targetlist of this node's input node
|
||||
* refnames_tlist: targetlist to take column names from
|
||||
*/
|
||||
static List *
|
||||
generate_setop_tlist(List *colTypes, int flag,
|
||||
Index varno,
|
||||
bool hack_constants,
|
||||
List *input_tlist,
|
||||
List *refnames_tlist)
|
||||
@ -462,7 +469,7 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
|
||||
expr = (Node *) inputtle->expr;
|
||||
else
|
||||
expr = (Node *) makeVar(0,
|
||||
expr = (Node *) makeVar(varno,
|
||||
inputtle->resno,
|
||||
exprType((Node *) inputtle->expr),
|
||||
exprTypmod((Node *) inputtle->expr),
|
||||
@ -513,6 +520,7 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
*
|
||||
* The entries in the Append's targetlist should always be simple Vars;
|
||||
* we just have to make sure they have the right datatypes and typmods.
|
||||
* The Vars are always generated with varno 0.
|
||||
*/
|
||||
static List *
|
||||
generate_append_tlist(List *colTypes, bool flag,
|
||||
|
Reference in New Issue
Block a user