aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteManip.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-10-05 19:11:39 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-10-05 19:11:39 +0000
commit05e3d0ee8666b74f11ffad16f46e372459d6e53e (patch)
treeb273892bfda60f6bad315e84aaa2e9826e226931 /src/backend/rewrite/rewriteManip.c
parent5292637f52c6db8a22f99177f228273cb69fc510 (diff)
downloadpostgresql-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.c98
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 */