Reconsider mechanism for marking sub-selects that are at top level of
a qualification clause (and hence can get away with being sloppy about distinguishing FALSE from UNKNOWN). We need to know this in subselect.c; marking the subplans in setrefs.c is too late.
This commit is contained in:
parent
de432ce39e
commit
56e1aab286
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.137 2003/01/13 00:29:25 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.138 2003/01/13 18:10:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -777,7 +777,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
|
||||||
|
|
||||||
/* Expand SubLinks to SubPlans */
|
/* Expand SubLinks to SubPlans */
|
||||||
if (parse->hasSubLinks)
|
if (parse->hasSubLinks)
|
||||||
expr = SS_process_sublinks(expr);
|
expr = SS_process_sublinks(expr, (kind != EXPRKIND_TARGET));
|
||||||
|
|
||||||
/* Replace uplevel vars with Param nodes */
|
/* Replace uplevel vars with Param nodes */
|
||||||
if (PlannerQueryLevel > 1)
|
if (PlannerQueryLevel > 1)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.87 2003/01/10 21:08:11 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.88 2003/01/13 18:10:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -42,7 +42,6 @@ typedef struct
|
||||||
|
|
||||||
static void fix_expr_references(Plan *plan, Node *node);
|
static void fix_expr_references(Plan *plan, Node *node);
|
||||||
static bool fix_expr_references_walker(Node *node, void *context);
|
static bool fix_expr_references_walker(Node *node, void *context);
|
||||||
static void mark_qual_expressions(List *quals);
|
|
||||||
static void set_join_references(Join *join, List *rtable);
|
static void set_join_references(Join *join, List *rtable);
|
||||||
static void set_uppernode_references(Plan *plan, Index subvarno);
|
static void set_uppernode_references(Plan *plan, Index subvarno);
|
||||||
static Node *join_references_mutator(Node *node,
|
static Node *join_references_mutator(Node *node,
|
||||||
|
@ -89,12 +88,10 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
case T_SeqScan:
|
case T_SeqScan:
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
break;
|
break;
|
||||||
case T_IndexScan:
|
case T_IndexScan:
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
fix_expr_references(plan,
|
fix_expr_references(plan,
|
||||||
(Node *) ((IndexScan *) plan)->indxqual);
|
(Node *) ((IndexScan *) plan)->indxqual);
|
||||||
fix_expr_references(plan,
|
fix_expr_references(plan,
|
||||||
|
@ -103,7 +100,6 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
case T_TidScan:
|
case T_TidScan:
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
fix_expr_references(plan,
|
fix_expr_references(plan,
|
||||||
(Node *) ((TidScan *) plan)->tideval);
|
(Node *) ((TidScan *) plan)->tideval);
|
||||||
break;
|
break;
|
||||||
|
@ -118,7 +114,6 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
*/
|
*/
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
|
|
||||||
/* Recurse into subplan too */
|
/* Recurse into subplan too */
|
||||||
rte = rt_fetch(((SubqueryScan *) plan)->scan.scanrelid,
|
rte = rt_fetch(((SubqueryScan *) plan)->scan.scanrelid,
|
||||||
|
@ -134,7 +129,6 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
|
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
|
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
|
||||||
rtable);
|
rtable);
|
||||||
Assert(rte->rtekind == RTE_FUNCTION);
|
Assert(rte->rtekind == RTE_FUNCTION);
|
||||||
|
@ -145,17 +139,13 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
set_join_references((Join *) plan, rtable);
|
set_join_references((Join *) plan, rtable);
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
|
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
|
||||||
mark_qual_expressions(((Join *) plan)->joinqual);
|
|
||||||
break;
|
break;
|
||||||
case T_MergeJoin:
|
case T_MergeJoin:
|
||||||
set_join_references((Join *) plan, rtable);
|
set_join_references((Join *) plan, rtable);
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
|
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
|
||||||
mark_qual_expressions(((Join *) plan)->joinqual);
|
|
||||||
fix_expr_references(plan,
|
fix_expr_references(plan,
|
||||||
(Node *) ((MergeJoin *) plan)->mergeclauses);
|
(Node *) ((MergeJoin *) plan)->mergeclauses);
|
||||||
break;
|
break;
|
||||||
|
@ -163,9 +153,7 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
set_join_references((Join *) plan, rtable);
|
set_join_references((Join *) plan, rtable);
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
|
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
|
||||||
mark_qual_expressions(((Join *) plan)->joinqual);
|
|
||||||
fix_expr_references(plan,
|
fix_expr_references(plan,
|
||||||
(Node *) ((HashJoin *) plan)->hashclauses);
|
(Node *) ((HashJoin *) plan)->hashclauses);
|
||||||
break;
|
break;
|
||||||
|
@ -192,7 +180,6 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
set_uppernode_references(plan, (Index) 0);
|
set_uppernode_references(plan, (Index) 0);
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
break;
|
break;
|
||||||
case T_Result:
|
case T_Result:
|
||||||
|
|
||||||
|
@ -206,9 +193,7 @@ set_plan_references(Plan *plan, List *rtable)
|
||||||
set_uppernode_references(plan, (Index) OUTER);
|
set_uppernode_references(plan, (Index) OUTER);
|
||||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_expr_references(plan, (Node *) plan->qual);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
mark_qual_expressions(plan->qual);
|
|
||||||
fix_expr_references(plan, ((Result *) plan)->resconstantqual);
|
fix_expr_references(plan, ((Result *) plan)->resconstantqual);
|
||||||
mark_qual_expressions((List *) ((Result *) plan)->resconstantqual);
|
|
||||||
break;
|
break;
|
||||||
case T_Append:
|
case T_Append:
|
||||||
|
|
||||||
|
@ -283,28 +268,6 @@ fix_expr_references_walker(Node *node, void *context)
|
||||||
return expression_tree_walker(node, fix_expr_references_walker, context);
|
return expression_tree_walker(node, fix_expr_references_walker, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* mark_qual_expressions
|
|
||||||
* Do final cleanup on qualifier expressions (not targetlists!)
|
|
||||||
*
|
|
||||||
* SubPlans appearing at the top level of a qual expression are marked
|
|
||||||
* to indicate that they need not distinguish UNKNOWN (null) from FALSE
|
|
||||||
* results; this can save processing time in some cases.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
mark_qual_expressions(List *quals)
|
|
||||||
{
|
|
||||||
List *qual;
|
|
||||||
|
|
||||||
foreach(qual, quals)
|
|
||||||
{
|
|
||||||
Node *node = lfirst(qual);
|
|
||||||
|
|
||||||
if (IsA(node, SubPlan))
|
|
||||||
((SubPlan *) node)->unknownEqFalse = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set_join_references
|
* set_join_references
|
||||||
* Modifies the target list of a join node to reference its subplans,
|
* Modifies the target list of a join node to reference its subplans,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.65 2003/01/13 00:29:26 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.66 2003/01/13 18:10:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -65,7 +65,7 @@ static List *convert_sublink_opers(List *lefthand, List *operOids,
|
||||||
List *targetlist, List **paramIds);
|
List *targetlist, List **paramIds);
|
||||||
static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
|
static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
|
||||||
static Node *replace_correlation_vars_mutator(Node *node, void *context);
|
static Node *replace_correlation_vars_mutator(Node *node, void *context);
|
||||||
static Node *process_sublinks_mutator(Node *node, void *context);
|
static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
|
||||||
static bool finalize_primnode(Node *node, finalize_primnode_results *results);
|
static bool finalize_primnode(Node *node, finalize_primnode_results *results);
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,7 +159,8 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
|
||||||
* Convert a bare SubLink (as created by the parser) into a SubPlan.
|
* Convert a bare SubLink (as created by the parser) into a SubPlan.
|
||||||
*
|
*
|
||||||
* We are given the raw SubLink and the already-processed lefthand argument
|
* We are given the raw SubLink and the already-processed lefthand argument
|
||||||
* list (use this instead of the SubLink's own field).
|
* list (use this instead of the SubLink's own field). We are also told if
|
||||||
|
* this expression appears at top level of a WHERE/HAVING qual.
|
||||||
*
|
*
|
||||||
* The result is whatever we need to substitute in place of the SubLink
|
* The result is whatever we need to substitute in place of the SubLink
|
||||||
* node in the executable expression. This will be either the SubPlan
|
* node in the executable expression. This will be either the SubPlan
|
||||||
|
@ -168,7 +169,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
|
||||||
* containing InitPlan Param nodes.
|
* containing InitPlan Param nodes.
|
||||||
*/
|
*/
|
||||||
static Node *
|
static Node *
|
||||||
make_subplan(SubLink *slink, List *lefthand)
|
make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
|
||||||
{
|
{
|
||||||
SubPlan *node = makeNode(SubPlan);
|
SubPlan *node = makeNode(SubPlan);
|
||||||
Query *subquery = (Query *) (slink->subselect);
|
Query *subquery = (Query *) (slink->subselect);
|
||||||
|
@ -232,7 +233,8 @@ make_subplan(SubLink *slink, List *lefthand)
|
||||||
node->exprs = NIL;
|
node->exprs = NIL;
|
||||||
node->paramIds = NIL;
|
node->paramIds = NIL;
|
||||||
node->useHashTable = false;
|
node->useHashTable = false;
|
||||||
node->unknownEqFalse = false;
|
/* At top level of a qual, can treat UNKNOWN the same as FALSE */
|
||||||
|
node->unknownEqFalse = isTopQual;
|
||||||
node->setParam = NIL;
|
node->setParam = NIL;
|
||||||
node->parParam = NIL;
|
node->parParam = NIL;
|
||||||
node->args = NIL;
|
node->args = NIL;
|
||||||
|
@ -589,17 +591,23 @@ replace_correlation_vars_mutator(Node *node, void *context)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expand SubLinks to SubPlans in the given expression.
|
* Expand SubLinks to SubPlans in the given expression.
|
||||||
|
*
|
||||||
|
* The isQual argument tells whether or not this expression is a WHERE/HAVING
|
||||||
|
* qualifier expression. If it is, any sublinks appearing at top level need
|
||||||
|
* not distinguish FALSE from UNKNOWN return values.
|
||||||
*/
|
*/
|
||||||
Node *
|
Node *
|
||||||
SS_process_sublinks(Node *expr)
|
SS_process_sublinks(Node *expr, bool isQual)
|
||||||
{
|
{
|
||||||
/* No setup needed for tree walk, so away we go */
|
/* The only context needed is the initial are-we-in-a-qual flag */
|
||||||
return process_sublinks_mutator(expr, NULL);
|
return process_sublinks_mutator(expr, &isQual);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *
|
static Node *
|
||||||
process_sublinks_mutator(Node *node, void *context)
|
process_sublinks_mutator(Node *node, bool *isTopQual)
|
||||||
{
|
{
|
||||||
|
bool locTopQual;
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (IsA(node, SubLink))
|
if (IsA(node, SubLink))
|
||||||
|
@ -610,12 +618,13 @@ process_sublinks_mutator(Node *node, void *context)
|
||||||
/*
|
/*
|
||||||
* First, recursively process the lefthand-side expressions, if any.
|
* First, recursively process the lefthand-side expressions, if any.
|
||||||
*/
|
*/
|
||||||
|
locTopQual = false;
|
||||||
lefthand = (List *)
|
lefthand = (List *)
|
||||||
process_sublinks_mutator((Node *) sublink->lefthand, context);
|
process_sublinks_mutator((Node *) sublink->lefthand, &locTopQual);
|
||||||
/*
|
/*
|
||||||
* Now build the SubPlan node and make the expr to return.
|
* Now build the SubPlan node and make the expr to return.
|
||||||
*/
|
*/
|
||||||
return make_subplan(sublink, lefthand);
|
return make_subplan(sublink, lefthand, *isTopQual);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -626,9 +635,18 @@ process_sublinks_mutator(Node *node, void *context)
|
||||||
*/
|
*/
|
||||||
Assert(!is_subplan(node));
|
Assert(!is_subplan(node));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we recurse down through anything other than a List node, we are
|
||||||
|
* definitely not at top qual level anymore.
|
||||||
|
*/
|
||||||
|
if (IsA(node, List))
|
||||||
|
locTopQual = *isTopQual;
|
||||||
|
else
|
||||||
|
locTopQual = false;
|
||||||
|
|
||||||
return expression_tree_mutator(node,
|
return expression_tree_mutator(node,
|
||||||
process_sublinks_mutator,
|
process_sublinks_mutator,
|
||||||
context);
|
(void *) &locTopQual);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -16,6 +16,6 @@ extern int PlannerPlanId; /* to assign unique ID to subquery plans */
|
||||||
|
|
||||||
extern List *SS_finalize_plan(Plan *plan, List *rtable);
|
extern List *SS_finalize_plan(Plan *plan, List *rtable);
|
||||||
extern Node *SS_replace_correlation_vars(Node *expr);
|
extern Node *SS_replace_correlation_vars(Node *expr);
|
||||||
extern Node *SS_process_sublinks(Node *expr);
|
extern Node *SS_process_sublinks(Node *expr, bool isQual);
|
||||||
|
|
||||||
#endif /* SUBSELECT_H */
|
#endif /* SUBSELECT_H */
|
||||||
|
|
Loading…
Reference in New Issue