diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-05-10 22:44:49 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-05-10 22:44:49 +0000 |
commit | 2f63232d30ca64a8f2684af855230f23a701d371 (patch) | |
tree | b7a7707d1ec9edf368780cd3f4a23755527c5884 /src/backend/optimizer/util/var.c | |
parent | 9a939886ac782cfee3cd5fdd1c58689163ed84be (diff) | |
download | postgresql-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.c | 53 |
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); /* |