mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Track nesting depth correctly when drilling down into RECORD Vars.
expandRecordVariable() failed to adjust the parse nesting structure correctly when recursing to inspect an outer-level Var. This could result in assertion failures or core dumps in corner cases. Likewise, get_name_for_var_field() failed to adjust the deparse namespace stack correctly when recursing to inspect an outer-level Var. In this case the likely result was a "bogus varno" error while deparsing a view. Per bug #18077 from Jingzhou Fu. Back-patch to all supported branches. Richard Guo, with some adjustments by me Discussion: https://postgr.es/m/18077-b9db97c6e0ab45d8@postgresql.org
This commit is contained in:
@ -1475,7 +1475,8 @@ ExpandRowReference(ParseState *pstate, Node *expr,
|
||||
* drill down to find the ultimate defining expression and attempt to infer
|
||||
* the tupdesc from it. We ereport if we can't determine the tupdesc.
|
||||
*
|
||||
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
|
||||
* levelsup is an extra offset to interpret the Var's varlevelsup correctly
|
||||
* when recursing. Outside callers should pass zero.
|
||||
*/
|
||||
TupleDesc
|
||||
expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
||||
@ -1563,11 +1564,17 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
||||
/*
|
||||
* Recurse into the sub-select to see what its Var refers
|
||||
* to. We have to build an additional level of ParseState
|
||||
* to keep in step with varlevelsup in the subselect.
|
||||
* to keep in step with varlevelsup in the subselect;
|
||||
* furthermore, the subquery RTE might be from an outer
|
||||
* query level, in which case the ParseState for the
|
||||
* subselect must have that outer level as parent.
|
||||
*/
|
||||
ParseState mypstate;
|
||||
ParseState mypstate = {0};
|
||||
Index levelsup;
|
||||
|
||||
MemSet(&mypstate, 0, sizeof(mypstate));
|
||||
/* this loop must work, since GetRTEByRangeTablePosn did */
|
||||
for (levelsup = 0; levelsup < netlevelsup; levelsup++)
|
||||
pstate = pstate->parentParseState;
|
||||
mypstate.parentParseState = pstate;
|
||||
mypstate.p_rtable = rte->subquery->rtable;
|
||||
/* don't bother filling the rest of the fake pstate */
|
||||
@ -1618,12 +1625,11 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
||||
* Recurse into the CTE to see what its Var refers to. We
|
||||
* have to build an additional level of ParseState to keep
|
||||
* in step with varlevelsup in the CTE; furthermore it
|
||||
* could be an outer CTE.
|
||||
* could be an outer CTE (compare SUBQUERY case above).
|
||||
*/
|
||||
ParseState mypstate;
|
||||
ParseState mypstate = {0};
|
||||
Index levelsup;
|
||||
|
||||
MemSet(&mypstate, 0, sizeof(mypstate));
|
||||
/* this loop must work, since GetCTEForRTE did */
|
||||
for (levelsup = 0;
|
||||
levelsup < rte->ctelevelsup + netlevelsup;
|
||||
|
Reference in New Issue
Block a user