diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-10-05 19:11:39 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-10-05 19:11:39 +0000 |
commit | 05e3d0ee8666b74f11ffad16f46e372459d6e53e (patch) | |
tree | b273892bfda60f6bad315e84aaa2e9826e226931 /src/backend/rewrite/rewriteManip.c | |
parent | 5292637f52c6db8a22f99177f228273cb69fc510 (diff) | |
download | postgresql-05e3d0ee8666b74f11ffad16f46e372459d6e53e.tar.gz postgresql-05e3d0ee8666b74f11ffad16f46e372459d6e53e.zip |
Reimplementation of UNION/INTERSECT/EXCEPT. INTERSECT/EXCEPT now meet the
SQL92 semantics, including support for ALL option. All three can be used
in subqueries and views. DISTINCT and ORDER BY work now in views, too.
This rewrite fixes many problems with cross-datatype UNIONs and INSERT/SELECT
where the SELECT yields different datatypes than the INSERT needs. I did
that by making UNION subqueries and SELECT in INSERT be treated like
subselects-in-FROM, thereby allowing an extra level of targetlist where the
datatype conversions can be inserted safely.
INITDB NEEDED!
Diffstat (limited to 'src/backend/rewrite/rewriteManip.c')
-rw-r--r-- | src/backend/rewrite/rewriteManip.c | 98 |
1 files changed, 45 insertions, 53 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 0b07b5e9c46..cffe624deb4 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.49 2000/09/29 18:21:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.50 2000/10/05 19:11:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,7 +48,7 @@ checkExprHasAggs(Node *node) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, checkExprHasAggs_walker, - NULL); + NULL, false); else return checkExprHasAggs_walker(node, NULL); } @@ -78,7 +78,7 @@ checkExprHasSubLink(Node *node) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, checkExprHasSubLink_walker, - NULL); + NULL, false); else return checkExprHasSubLink_walker(node, NULL); } @@ -101,7 +101,7 @@ checkExprHasSubLink_walker(Node *node, void *context) * Find all Var nodes in the given tree with varlevelsup == sublevels_up, * and increment their varno fields (rangetable indexes) by 'offset'. * The varnoold fields are adjusted similarly. Also, RangeTblRef nodes - * in join trees are adjusted. + * in join trees and setOp trees are adjusted. * * NOTE: although this has the form of a walker, we cheat and modify the * nodes in-place. The given expression tree should have been copied @@ -136,6 +136,7 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context) if (context->sublevels_up == 0) rtr->rtindex += context->offset; + /* the subquery itself is visited separately */ return false; } if (IsA(node, Query)) @@ -145,7 +146,7 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, OffsetVarNodes_walker, - (void *) context); + (void *) context, true); context->sublevels_up--; return result; } @@ -168,7 +169,7 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) */ if (node && IsA(node, Query)) query_tree_walker((Query *) node, OffsetVarNodes_walker, - (void *) &context); + (void *) &context, true); else OffsetVarNodes_walker(node, &context); } @@ -179,7 +180,7 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) * Find all Var nodes in the given tree belonging to a specific relation * (identified by sublevels_up and rt_index), and change their varno fields * to 'new_index'. The varnoold fields are changed too. Also, RangeTblRef - * nodes in join trees are adjusted. + * nodes in join trees and setOp trees are adjusted. * * NOTE: although this has the form of a walker, we cheat and modify the * nodes in-place. The given expression tree should have been copied @@ -217,6 +218,7 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) if (context->sublevels_up == 0 && rtr->rtindex == context->rt_index) rtr->rtindex = context->new_index; + /* the subquery itself is visited separately */ return false; } if (IsA(node, Query)) @@ -226,7 +228,7 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, ChangeVarNodes_walker, - (void *) context); + (void *) context, true); context->sublevels_up--; return result; } @@ -250,7 +252,7 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) */ if (node && IsA(node, Query)) query_tree_walker((Query *) node, ChangeVarNodes_walker, - (void *) &context); + (void *) &context, true); else ChangeVarNodes_walker(node, &context); } @@ -300,7 +302,7 @@ IncrementVarSublevelsUp_walker(Node *node, context->min_sublevels_up++; result = query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker, - (void *) context); + (void *) context, true); context->min_sublevels_up--; return result; } @@ -324,7 +326,7 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, */ if (node && IsA(node, Query)) query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker, - (void *) &context); + (void *) &context, true); else IncrementVarSublevelsUp_walker(node, &context); } @@ -332,7 +334,7 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, /* * rangeTableEntry_used - detect whether an RTE is referenced somewhere - * in var nodes or jointree nodes of a query or expression. + * in var nodes or join or setOp trees of a query or expression. */ typedef struct @@ -363,6 +365,7 @@ rangeTableEntry_used_walker(Node *node, if (rtr->rtindex == context->rt_index && context->sublevels_up == 0) return true; + /* the subquery itself is visited separately */ return false; } if (IsA(node, Query)) @@ -372,7 +375,7 @@ rangeTableEntry_used_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, rangeTableEntry_used_walker, - (void *) context); + (void *) context, true); context->sublevels_up--; return result; } @@ -395,7 +398,7 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, rangeTableEntry_used_walker, - (void *) &context); + (void *) &context, true); else return rangeTableEntry_used_walker(node, &context); } @@ -437,7 +440,7 @@ attribute_used_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, attribute_used_walker, - (void *) context); + (void *) context, true); context->sublevels_up--; return result; } @@ -461,7 +464,7 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, attribute_used_walker, - (void *) &context); + (void *) &context, true); else return attribute_used_walker(node, &context); } @@ -681,10 +684,8 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context) FLATCOPY(newnode, sublink, SubLink); MUTATE(newnode->lefthand, sublink->lefthand, List *, ResolveNew_mutator, context); - context->sublevels_up++; MUTATE(newnode->subselect, sublink->subselect, Node *, ResolveNew_mutator, context); - context->sublevels_up--; return (Node *) newnode; } if (IsA(node, Query)) @@ -693,12 +694,9 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context) Query *newnode; FLATCOPY(newnode, query, Query); - MUTATE(newnode->targetList, query->targetList, List *, - ResolveNew_mutator, context); - MUTATE(newnode->jointree, query->jointree, FromExpr *, - ResolveNew_mutator, context); - MUTATE(newnode->havingQual, query->havingQual, Node *, - ResolveNew_mutator, context); + context->sublevels_up++; + query_tree_mutator(newnode, ResolveNew_mutator, context, true); + context->sublevels_up--; return (Node *) newnode; } return expression_tree_mutator(node, ResolveNew_mutator, @@ -718,11 +716,22 @@ ResolveNew(Node *node, int target_varno, int sublevels_up, context.update_varno = update_varno; /* - * Note: if an entire Query is passed, the right things will happen, - * because ResolveNew_mutator increments sublevels_up when it sees - * a SubLink, not a Query. + * Must be prepared to start with a Query or a bare expression tree; + * if it's a Query, go straight to query_tree_mutator to make sure that + * sublevels_up doesn't get incremented prematurely. */ - return ResolveNew_mutator(node, &context); + if (node && IsA(node, Query)) + { + Query *query = (Query *) node; + Query *newnode; + + FLATCOPY(newnode, query, Query); + query_tree_mutator(newnode, ResolveNew_mutator, + (void *) &context, true); + return (Node *) newnode; + } + else + return ResolveNew_mutator(node, &context); } /* @@ -740,12 +749,8 @@ FixNew(RewriteInfo *info, Query *parsetree) context.event = info->event; context.update_varno = info->current_varno; - info->rule_action->targetList = (List *) - ResolveNew_mutator((Node *) info->rule_action->targetList, &context); - info->rule_action->jointree = (FromExpr *) - ResolveNew_mutator((Node *) info->rule_action->jointree, &context); - info->rule_action->havingQual = - ResolveNew_mutator(info->rule_action->havingQual, &context); + query_tree_mutator(info->rule_action, ResolveNew_mutator, + (void *) &context, true); } @@ -837,10 +842,8 @@ HandleRIRAttributeRule_mutator(Node *node, FLATCOPY(newnode, sublink, SubLink); MUTATE(newnode->lefthand, sublink->lefthand, List *, HandleRIRAttributeRule_mutator, context); - context->sublevels_up++; MUTATE(newnode->subselect, sublink->subselect, Node *, HandleRIRAttributeRule_mutator, context); - context->sublevels_up--; return (Node *) newnode; } if (IsA(node, Query)) @@ -849,14 +852,10 @@ HandleRIRAttributeRule_mutator(Node *node, Query *newnode; FLATCOPY(newnode, query, Query); - MUTATE(newnode->targetList, query->targetList, List *, - HandleRIRAttributeRule_mutator, context); - MUTATE(newnode->jointree, query->jointree, FromExpr *, - HandleRIRAttributeRule_mutator, context); - MUTATE(newnode->havingQual, query->havingQual, Node *, - HandleRIRAttributeRule_mutator, context); - - + context->sublevels_up++; + query_tree_mutator(newnode, HandleRIRAttributeRule_mutator, + context, true); + context->sublevels_up--; return (Node *) newnode; } return expression_tree_mutator(node, HandleRIRAttributeRule_mutator, @@ -882,15 +881,8 @@ HandleRIRAttributeRule(Query *parsetree, context.badsql = badsql; context.sublevels_up = 0; - parsetree->targetList = (List *) - HandleRIRAttributeRule_mutator((Node *) parsetree->targetList, - &context); - parsetree->jointree = (FromExpr *) - HandleRIRAttributeRule_mutator((Node *) parsetree->jointree, - &context); - parsetree->havingQual = - HandleRIRAttributeRule_mutator(parsetree->havingQual, - &context); + query_tree_mutator(parsetree, HandleRIRAttributeRule_mutator, + (void *) &context, true); } #endif /* NOT_USED */ |