1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +03:00

Change post-rewriter representation of dropped columns in joinaliasvars.

It's possible to drop a column from an input table of a JOIN clause in a
view, if that column is nowhere actually referenced in the view.  But it
will still be there in the JOIN clause's joinaliasvars list.  We used to
replace such entries with NULL Const nodes, which is handy for generation
of RowExpr expansion of a whole-row reference to the view.  The trouble
with that is that it can't be distinguished from the situation after
subquery pull-up of a constant subquery output expression below the JOIN.
Instead, replace such joinaliasvars with null pointers (empty expression
trees), which can't be confused with pulled-up expressions.  expandRTE()
still emits the old convention, though, for convenience of RowExpr
generation and to reduce the risk of breaking extension code.

In HEAD and 9.3, this patch also fixes a problem with some new code in
ruleutils.c that was failing to cope with implicitly-casted joinaliasvars
entries, as per recent report from Feike Steenbergen.  That oversight was
because of an inadequate description of the data structure in parsenodes.h,
which I've now corrected.  There were some pre-existing oversights of the
same ilk elsewhere, which I believe are now all fixed.
This commit is contained in:
Tom Lane
2013-07-23 16:23:04 -04:00
parent 5712eeb2e7
commit b81d0691b9
8 changed files with 119 additions and 51 deletions

View File

@ -19,6 +19,7 @@
#include "foreign/fdwapi.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parsetree.h"
@ -90,9 +91,8 @@ static Query *fireRIRrules(Query *parsetree, List *activeRIRs,
* such a list in a stored rule to include references to dropped columns.
* (If the column is not explicitly referenced anywhere else in the query,
* the dependency mechanism won't consider it used by the rule and so won't
* prevent the column drop.) To support get_rte_attribute_is_dropped(),
* we replace join alias vars that reference dropped columns with NULL Const
* nodes.
* prevent the column drop.) To support get_rte_attribute_is_dropped(), we
* replace join alias vars that reference dropped columns with null pointers.
*
* (In PostgreSQL 8.0, we did not do this processing but instead had
* get_rte_attribute_is_dropped() recurse to detect dropped columns in joins.
@ -159,8 +159,8 @@ AcquireRewriteLocks(Query *parsetree, bool forUpdatePushedDown)
/*
* Scan the join's alias var list to see if any columns have
* been dropped, and if so replace those Vars with NULL
* Consts.
* been dropped, and if so replace those Vars with null
* pointers.
*
* Since a join has only two inputs, we can expect to see
* multiple references to the same input RTE; optimize away
@ -171,16 +171,20 @@ AcquireRewriteLocks(Query *parsetree, bool forUpdatePushedDown)
curinputrte = NULL;
foreach(ll, rte->joinaliasvars)
{
Var *aliasvar = (Var *) lfirst(ll);
Var *aliasitem = (Var *) lfirst(ll);
Var *aliasvar = aliasitem;
/* Look through any implicit coercion */
aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar);
/*
* If the list item isn't a simple Var, then it must
* represent a merged column, ie a USING column, and so it
* couldn't possibly be dropped, since it's referenced in
* the join clause. (Conceivably it could also be a NULL
* constant already? But that's OK too.)
* the join clause. (Conceivably it could also be a null
* pointer already? But that's OK too.)
*/
if (IsA(aliasvar, Var))
if (aliasvar && IsA(aliasvar, Var))
{
/*
* The elements of an alias list have to refer to
@ -204,15 +208,11 @@ AcquireRewriteLocks(Query *parsetree, bool forUpdatePushedDown)
if (get_rte_attribute_is_dropped(curinputrte,
aliasvar->varattno))
{
/*
* can't use vartype here, since that might be a
* now-dropped type OID, but it doesn't really
* matter what type the Const claims to be.
*/
aliasvar = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
/* Replace the join alias item with a NULL */
aliasitem = NULL;
}
}
newaliasvars = lappend(newaliasvars, aliasvar);
newaliasvars = lappend(newaliasvars, aliasitem);
}
rte->joinaliasvars = newaliasvars;
break;