diff options
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 147 |
1 files changed, 84 insertions, 63 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 7e76498f86a..714f08c2629 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.70 2000/04/04 02:30:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.71 2000/04/12 17:15:32 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -55,19 +55,19 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree, bool *instead_flag); static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up); static bool attribute_used(Node *node, int rt_index, int attno, - int sublevels_up); + int sublevels_up); static bool modifyAggrefChangeVarnodes(Node *node, int rt_index, int new_index, - int sublevels_up, int new_sublevels_up); + int sublevels_up, int new_sublevels_up); static Node *modifyAggrefDropQual(Node *node, Node *targetNode); static SubLink *modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree); static Node *modifyAggrefQual(Node *node, Query *parsetree); static Query *fireRIRrules(Query *parsetree); static Query *Except_Intersect_Rewrite(Query *parsetree); static void check_targetlists_are_compatible(List *prev_target, - List *current_target); + List *current_target); static void create_intersect_list(Node *ptr, List **intersect_list); static Node *intersect_tree_analyze(Node *tree, Node *first_select, - Node *parsetree); + Node *parsetree); /* * gatherRewriteMeta - @@ -148,14 +148,15 @@ gatherRewriteMeta(Query *parsetree, * referenced somewhere in var nodes of the query. */ -typedef struct { +typedef struct +{ int rt_index; int sublevels_up; } rangeTableEntry_used_context; static bool -rangeTableEntry_used_walker (Node *node, - rangeTableEntry_used_context *context) +rangeTableEntry_used_walker(Node *node, + rangeTableEntry_used_context *context) { if (node == NULL) return false; @@ -170,9 +171,10 @@ rangeTableEntry_used_walker (Node *node, } if (IsA(node, SubLink)) { + /* - * Standard expression_tree_walker will not recurse into subselect, - * but here we must do so. + * Standard expression_tree_walker will not recurse into + * subselect, but here we must do so. */ SubLink *sub = (SubLink *) node; @@ -218,15 +220,16 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up) * somewhere in the query */ -typedef struct { +typedef struct +{ int rt_index; int attno; int sublevels_up; } attribute_used_context; static bool -attribute_used_walker (Node *node, - attribute_used_context *context) +attribute_used_walker(Node *node, + attribute_used_context *context) { if (node == NULL) return false; @@ -242,9 +245,10 @@ attribute_used_walker (Node *node, } if (IsA(node, SubLink)) { + /* - * Standard expression_tree_walker will not recurse into subselect, - * but here we must do so. + * Standard expression_tree_walker will not recurse into + * subselect, but here we must do so. */ SubLink *sub = (SubLink *) node; @@ -296,11 +300,12 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) * not having the option to adjust the vars' varlevelsup. * * NOTE: although this has the form of a walker, we cheat and modify the - * Var nodes in-place. The given expression tree should have been copied + * Var nodes in-place. The given expression tree should have been copied * earlier to ensure that no unwanted side-effects occur! */ -typedef struct { +typedef struct +{ int rt_index; int new_index; int sublevels_up; @@ -309,7 +314,7 @@ typedef struct { static bool modifyAggrefChangeVarnodes_walker(Node *node, - modifyAggrefChangeVarnodes_context *context) + modifyAggrefChangeVarnodes_context *context) { if (node == NULL) return false; @@ -328,9 +333,10 @@ modifyAggrefChangeVarnodes_walker(Node *node, } if (IsA(node, SubLink)) { + /* - * Standard expression_tree_walker will not recurse into subselect, - * but here we must do so. + * Standard expression_tree_walker will not recurse into + * subselect, but here we must do so. */ SubLink *sub = (SubLink *) node; @@ -386,7 +392,7 @@ modifyAggrefChangeVarnodes(Node *node, int rt_index, int new_index, * targetNode is an Aggref node somewhere within the given expression tree. * Find the boolean operator that's presumably somewhere above it, and replace * that whole operator expression with a constant TRUE. (This is NOT really - * quite the right thing, but it handles simple cases. This whole set of + * quite the right thing, but it handles simple cases. This whole set of * Aggref-in-qual routines needs to be thrown away when we can do subselects * in FROM.) * @@ -439,8 +445,10 @@ static SubLink * modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree) { List *aggVarNos; + /* rte points to old structure: */ RangeTblEntry *rte; + /* these point to newly-created structures: */ Query *subquery; SubLink *sublink; @@ -463,7 +471,7 @@ modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree) tle = makeNode(TargetEntry); tle->resdom = resdom; - tle->expr = copyObject(aggref); /* make a modifiable copy! */ + tle->expr = copyObject(aggref); /* make a modifiable copy! */ subquery = makeNode(Query); @@ -488,10 +496,11 @@ modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree) subquery->targetList = lcons(tle, NIL); subquery->qual = modifyAggrefDropQual((Node *) parsetree->qual, (Node *) aggref); + /* - * If there are still aggs in the subselect's qual, give up. - * Recursing would be a bad idea --- we'd likely produce an - * infinite recursion. This whole technique is a crock, really... + * If there are still aggs in the subselect's qual, give up. Recursing + * would be a bad idea --- we'd likely produce an infinite recursion. + * This whole technique is a crock, really... */ if (checkExprHasAggs(subquery->qual)) elog(ERROR, "Cannot handle multiple aggregate functions in WHERE clause"); @@ -504,7 +513,8 @@ modifyAggrefMakeSublink(Aggref *aggref, Query *parsetree) /* Increment all varlevelsup fields in the new subquery */ IncrementVarSublevelsUp((Node *) subquery, 1, 0); - /* Replace references to the target table with correct local varno, 1. + /* + * Replace references to the target table with correct local varno, 1. * Note that because of previous line, these references have * varlevelsup = 1, which must be changed to 0. */ @@ -537,11 +547,12 @@ modifyAggrefQual(Node *node, Query *parsetree) parsetree->hasSubLinks = true; return (Node *) sub; } + /* * Otherwise, fall through and copy the expr normally. * - * We do NOT recurse into subselects in this routine. It's sufficient - * to get rid of aggregates that are in the qual expression proper. + * We do NOT recurse into subselects in this routine. It's sufficient to + * get rid of aggregates that are in the qual expression proper. */ return expression_tree_mutator(node, modifyAggrefQual, (void *) parsetree); @@ -585,12 +596,13 @@ make_null(Oid type) * Replace Vars matching a given RT index with copies of TL expressions. */ -typedef struct { - int rt_index; - int sublevels_up; - RangeTblEntry *rte; - List *tlist; - int *modified; +typedef struct +{ + int rt_index; + int sublevels_up; + RangeTblEntry *rte; + List *tlist; + int *modified; } apply_RIR_view_context; static Node * @@ -633,14 +645,15 @@ apply_RIR_view_mutator(Node *node, } /* otherwise fall through to copy the var normally */ } + /* * Since expression_tree_mutator won't touch subselects, we have to * handle them specially. */ if (IsA(node, SubLink)) { - SubLink *sublink = (SubLink *) node; - SubLink *newnode; + SubLink *sublink = (SubLink *) node; + SubLink *newnode; FLATCOPY(newnode, sublink, SubLink); MUTATE(newnode->lefthand, sublink->lefthand, List *, @@ -653,8 +666,8 @@ apply_RIR_view_mutator(Node *node, } if (IsA(node, Query)) { - Query *query = (Query *) node; - Query *newnode; + Query *query = (Query *) node; + Query *newnode; FLATCOPY(newnode, query, Query); MUTATE(newnode->targetList, query->targetList, List *, @@ -673,7 +686,7 @@ static Node * apply_RIR_view(Node *node, int rt_index, RangeTblEntry *rte, List *tlist, int *modified, int sublevels_up) { - apply_RIR_view_context context; + apply_RIR_view_context context; context.rt_index = rt_index; context.sublevels_up = sublevels_up; @@ -718,18 +731,20 @@ ApplyRetrieveRule(Query *parsetree, nothing = TRUE; rtable = copyObject(parsetree->rtable); - rt_length = length(rtable); /* original length, not counting rule */ + rt_length = length(rtable); /* original length, not counting rule */ addedrtable = copyObject(rule_action->rtable); - /* If the original rel wasn't in the join set, none of its spawn is. + /* + * If the original rel wasn't in the join set, none of its spawn is. * If it was, then leave the spawn's flags as they are. */ - if (! relWasInJoinSet) + if (!relWasInJoinSet) { foreach(l, addedrtable) { RangeTblEntry *rte = lfirst(l); + rte->inJoinSet = false; } } @@ -789,7 +804,7 @@ ApplyRetrieveRule(Query *parsetree, if (relation_level) { - RangeTblEntry *rte = rt_fetch(rt_index, rtable); + RangeTblEntry *rte = rt_fetch(rt_index, rtable); parsetree = (Query *) apply_RIR_view((Node *) parsetree, rt_index, rte, @@ -824,7 +839,7 @@ ApplyRetrieveRule(Query *parsetree, * Apply fireRIRrules() to each subselect found in the given tree. * * NOTE: although this has the form of a walker, we cheat and modify the - * SubLink nodes in-place. It is caller's responsibility to ensure that + * SubLink nodes in-place. It is caller's responsibility to ensure that * no unwanted side-effects occur! */ static bool @@ -883,8 +898,9 @@ fireRIRrules(Query *parsetree) int i; List *l; - /* don't try to convert this into a foreach loop, because - * rtable list can get changed each time through... + /* + * don't try to convert this into a foreach loop, because rtable list + * can get changed each time through... */ rt_index = 0; while (rt_index < length(parsetree->rtable)) @@ -894,13 +910,13 @@ fireRIRrules(Query *parsetree) rte = rt_fetch(rt_index, parsetree->rtable); /* - * If the table is not one named in the original FROM clause - * then it must be referenced in the query, or we ignore it. - * This prevents infinite expansion loop due to new rtable - * entries inserted by expansion of a rule. + * If the table is not one named in the original FROM clause then + * it must be referenced in the query, or we ignore it. This + * prevents infinite expansion loop due to new rtable entries + * inserted by expansion of a rule. */ - if (! rte->inFromCl && rt_index != parsetree->resultRelation && - ! rangeTableEntry_used((Node *) parsetree, rt_index, 0)) + if (!rte->inFromCl && rt_index != parsetree->resultRelation && + !rangeTableEntry_used((Node *) parsetree, rt_index, 0)) { /* Make sure the planner ignores it too... */ rte->inJoinSet = false; @@ -915,7 +931,8 @@ fireRIRrules(Query *parsetree) continue; } - relWasInJoinSet = rte->inJoinSet; /* save before possibly clearing */ + relWasInJoinSet = rte->inJoinSet; /* save before possibly + * clearing */ /* * Collect the RIR rules that we must apply @@ -930,16 +947,18 @@ fireRIRrules(Query *parsetree) if (rule->attrno > 0) { /* per-attr rule; do we need it? */ - if (! attribute_used((Node *) parsetree, - rt_index, - rule->attrno, 0)) + if (!attribute_used((Node *) parsetree, + rt_index, + rule->attrno, 0)) continue; } else { - /* Rel-wide ON SELECT DO INSTEAD means this is a view. - * Remove the view from the planner's join target set, - * or we'll get no rows out because view itself is empty! + + /* + * Rel-wide ON SELECT DO INSTEAD means this is a view. + * Remove the view from the planner's join target set, or + * we'll get no rows out because view itself is empty! */ if (rule->isInstead) rte->inJoinSet = false; @@ -1448,7 +1467,7 @@ BasicQueryRewrite(Query *parsetree) /* * If the query was marked having aggregates, check if this is - * still true after rewriting. Ditto for sublinks. Note there + * still true after rewriting. Ditto for sublinks. Note there * should be no aggs in the qual at this point. */ if (query->hasAggs) @@ -1663,6 +1682,7 @@ Except_Intersect_Rewrite(Query *parsetree) */ if (parsetree->commandType == CMD_INSERT) { + /* * The result relation ( = the one to insert into) has to be * attached to the rtable list of the new top node @@ -1825,7 +1845,8 @@ Except_Intersect_Rewrite(Query *parsetree) /* * Also prepare the list of Opers that must be used for the - * comparisons (they depend on the specific datatypes involved!) + * comparisons (they depend on the specific datatypes + * involved!) */ left_expr = n->lefthand; right_expr = ((Query *) (n->subselect))->targetList; @@ -1848,8 +1869,8 @@ Except_Intersect_Rewrite(Query *parsetree) if (opform->oprresult != BOOLOID) elog(ERROR, "parser: '%s' must return 'bool' to be used with quantified predicate subquery", op); - newop = makeOper(oprid(optup),/* opno */ - InvalidOid, /* opid */ + newop = makeOper(oprid(optup), /* opno */ + InvalidOid, /* opid */ opform->oprresult, 0, NULL); |