From: | Craig Ringer <craig(at)2ndquadrant(dot)com> |
---|---|
To: | Abbas Butt <abbas(dot)butt(at)enterprisedb(dot)com> |
Cc: | PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: varattno remapping |
Date: | 2013-12-24 12:12:35 |
Message-ID: | 52B97A33.9080303@2ndquadrant.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
On 12/24/2013 03:21 PM, Abbas Butt wrote:
> Could you please explain a little bit more how would you solve the posed
> problem using map_variable_attnos?
It actually turns out to be even simpler, and easy to do in one pass,
when using ReplaceVarsFromTargetList .
You just generate a temporary new list of TargetEntry, with resnos
matching the attribute numbers of the view. Each contained Var points to
the remapped varno and varattno.
Then you let ReplaceVarsFromTargetList substitute Vars recursively
through the expression tree with ones in the replacement tlist you supply.
The more I've thought about it, the shorter this code has got. Currently:
/*
* Scan the passed view target list, whose members must consist solely
* of Var nodes with a varno equal to the passed targetvarno, and
* produce a targetlist of Var nodes with the corresponding varno and
* varattno of the base relation 'targetvarno'.
*
* This tlist is used when remapping Vars that point to a view so they
* point to the base relation of the view instead. It is entirely
* newly allocated. The result tlist is not in resno order.
*
* Must not be called with a targetlist containing non-Var entries.
*/
static List *
gen_view_base_attr_map(List *viewtlist, int targetvarno, int newvarno)
{
ListCell *lc;
TargetEntry *te, *newte;
Var *tev, *newvar;
int l_viewtlist = list_length(viewtlist);
List *newtlist = NIL;
foreach(lc, viewtlist)
{
te = (TargetEntry*) lfirst(lc);
/* Could relax this in future and map only the var entries,
* ignoring everything else, but currently pointless since we
* are only interested in simple views. */
Assert(IsA(te->expr, Var));
tev = (Var*) te->expr;
Assert(tev->varno == targetvarno);
Assert(te->resno - 1 < l_viewtlist);
/* Construct the new Var with the remapped attno and varno */
newvar = (Var*) palloc(sizeof(Var));
*newvar = *tev;
newvar->varno = newvarno;
newvar->varattno = tev->varattno;
/* and wrap it in a new tle to cons to the list */
newte = flatCopyTargetEntry(te);
newte->expr = (Expr*) newvar;
newtlist = lcons(newte, newtlist);
}
return newtlist;
}
and invocation:
/*
* We need to adjust any RETURNING clause entries to point to the new
* target RTE instead of the old one so that we see the effects of
* BEFORE triggers. Varattnos must be remapped so that the new Var
* points to the correct col of the base rel, since the view will
* usually have a different set of columns / column order.
*
* As part of this pass any whole-row references to the view are
* expanded into ROW(...) expressions to ensure we don't expose
* columns that are not visible through the view, and to make sure
* the client gets the result type it expected.
*/
List * remap_tlist = gen_view_base_attr_map(
viewquery->targetList, rtr->rtindex, new_result_rt_index);
parsetree->returningList = ReplaceVarsFromTargetList(
(Node*) parsetree->returningList,
old_result_rt_index, 0 /*sublevels_up*/,
view_rte,
remap_tlist,
REPLACEVARS_REPORT_ERROR, 0 /*nomatch_varno, unused */,
NULL /* outer_hasSubLinks, unused */
);
--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
From | Date | Subject | |
---|---|---|---|
Next Message | Andres Freund | 2013-12-24 12:24:15 | Re: Assertion failure in base backup code path |
Previous Message | Andres Freund | 2013-12-24 12:09:01 | Re: INSERT...ON DUPLICATE KEY LOCK FOR UPDATE |