aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/var.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-05-10 22:44:49 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-05-10 22:44:49 +0000
commit2f63232d30ca64a8f2684af855230f23a701d371 (patch)
treeb7a7707d1ec9edf368780cd3f4a23755527c5884 /src/backend/optimizer/util/var.c
parent9a939886ac782cfee3cd5fdd1c58689163ed84be (diff)
downloadpostgresql-2f63232d30ca64a8f2684af855230f23a701d371.tar.gz
postgresql-2f63232d30ca64a8f2684af855230f23a701d371.zip
Promote row expressions to full-fledged citizens of the expression syntax,
rather than allowing them only in a few special cases as before. In particular you can now pass a ROW() construct to a function that accepts a rowtype parameter. Internal generation of RowExprs fixes a number of corner cases that used to not work very well, such as referencing the whole-row result of a JOIN or subquery. This represents a further step in the work I started a month or so back to make rowtype values into first-class citizens.
Diffstat (limited to 'src/backend/optimizer/util/var.c')
-rw-r--r--src/backend/optimizer/util/var.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index dac90809de1..47b1fdbf70e 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.55 2003/11/29 19:51:51 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.56 2004/05/10 22:44:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -192,19 +192,6 @@ contain_var_reference_walker(Node *node,
/*
- * contain_whole_tuple_var
- *
- * Detect whether a parsetree contains any references to the whole
- * tuple of a given rtable entry (ie, a Var with varattno = 0).
- */
-bool
-contain_whole_tuple_var(Node *node, int varno, int levelsup)
-{
- return contain_var_reference(node, varno, InvalidAttrNumber, levelsup);
-}
-
-
-/*
* contain_var_clause
* Recursively scan a clause to discover whether it contains any Var nodes
* (of the current query level).
@@ -486,7 +473,10 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
* flatten_join_alias_vars
* Replace Vars that reference JOIN outputs with references to the original
* relation variables instead. This allows quals involving such vars to be
- * pushed down.
+ * pushed down. Whole-row Vars that reference JOIN relations are expanded
+ * into RowExpr constructs that name the individual output Vars. This
+ * is necessary since we will not scan the JOIN as a base relation, which
+ * is the only way that the executor can directly handle whole-row Vars.
*
* NOTE: this is used on not-yet-planned expressions. We do not expect it
* to be applied directly to a Query node.
@@ -520,8 +510,39 @@ flatten_join_alias_vars_mutator(Node *node,
rte = rt_fetch(var->varno, context->root->rtable);
if (rte->rtekind != RTE_JOIN)
return node;
+ if (var->varattno == InvalidAttrNumber)
+ {
+ /* Must expand whole-row reference */
+ RowExpr *rowexpr;
+ List *fields = NIL;
+ List *l;
+
+ foreach(l, rte->joinaliasvars)
+ {
+ newvar = (Node *) lfirst(l);
+ /*
+ * If we are expanding an alias carried down from an upper
+ * query, must adjust its varlevelsup fields.
+ */
+ if (context->sublevels_up != 0)
+ {
+ newvar = copyObject(newvar);
+ IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
+ }
+ /* Recurse in case join input is itself a join */
+ newvar = flatten_join_alias_vars_mutator(newvar, context);
+ fields = lappend(fields, newvar);
+ }
+ rowexpr = makeNode(RowExpr);
+ rowexpr->args = fields;
+ rowexpr->row_typeid = var->vartype;
+ rowexpr->row_format = COERCE_IMPLICIT_CAST;
+
+ return (Node *) rowexpr;
+ }
+
+ /* Expand join alias reference */
Assert(var->varattno > 0);
- /* Okay, must expand it */
newvar = (Node *) nth(var->varattno - 1, rte->joinaliasvars);
/*