Re: varattno remapping
От | Craig Ringer |
---|---|
Тема | Re: varattno remapping |
Дата | |
Msg-id | 52B965FE.5020703@2ndquadrant.com обсуждение исходный текст |
Ответ на | Re: varattno remapping (Abbas Butt <abbas.butt@enterprisedb.com>) |
Список | 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? > > I was recently working on a similar problem and used the following algo > to solve it. > > I had to find to which column of the base table does a column in > the select statement of the view query belong. > To relate a target list entry in the select query of the view to > an actual column in base table. Sounds similar. My problem is simplified by the constraint that the view must be a simple view (only one base relation) and must only contain simple column-references to single the base relation. No expressions, no joins. (These are the rules for simply updatable views). I'm new to the planner and rewriter, so don't take what I do as any kind of example beyond "this seems to work". I generate a varattno mapping as follows: /** Scan the passed view target list, whose members must consist solely* of Var nodes with a varno equal to the passed targetvarno.**A mapping is built from the resno (i.e. tlist index) of the view* tlist to the corresponding attribute numberof the base relation* the varattno points to.** Must not be called with a targetlist containing non-Var entries.*/ static void gen_view_base_attr_map(List *viewtlist, AttrNumber * attnomap, int targetvarno) { ListCell *lc; TargetEntry *te; Var *tev; int l_viewtlist = list_length(viewtlist); foreach(lc, viewtlist) { te = (TargetEntry*) lfirst(lc); /* Could relax this in future and map only thevar entries, * ignoring everything else, but currently pointless since we * are only interested in simpleviews. */ Assert(IsA(te->expr, Var)); tev = (Var*) te->expr; Assert(tev->varno == targetvarno); Assert(te->resno - 1 < l_viewtlist); attnomap[te->resno - 1] = tev->varattno; } } producing a forward mapping of view attno to base relation attno. I then apply the varattno remapping, in this case to the returning list of a DML query acting on a view, with something like: varattno_map = palloc( list_length(viewquery->targetList) * sizeof(AttrNumber) ); gen_view_base_attr_map(viewquery->targetList, varattno_map, rtr->rtindex); parsetree->returningList = map_variable_attnos( (Node*) parsetree->returningList, old_result_rt_index,0, varattno_map, list_length(viewquery->targetList), &found_whole_row_var ); if (found_whole_row_var) { /* TODO: Extend map_variable_attnos API to pass a mutator to handle whole-rowvars. */ elog(ERROR, "RETURNING list contains a whole-row variable, " "which is not currentlysupported for updatable " "views"); } ChangeVarNodes((Node*) parsetree->returningList, old_result_rt_index, new_result_rt_index, 0); I'd prefer to be doing the map_variable_attnos and ChangeVarNodes work in a single pass, but it looks like a clumsy and verbose process to write a new walker. So I'm going to leave it as an "opportunity for future optimisation" for now ;-) (As it happens that "found_whole_row_var" is a real pain; I'm going to have to deal with a TODO item in map_variable_attnos to provide a callback that replaces a whole-row Var with an expansion of it into a row-expression). -- Craig Ringer http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training & Services
В списке pgsql-hackers по дате отправления: