aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_target.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2023-09-15 17:01:26 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2023-09-15 17:01:52 -0400
commite0e492e5a928e9c9eda01eeebadcfc36f9f8e7b7 (patch)
tree49c817e2514dd2cfc077ce361d70e084cee1725a /src/backend/parser/parse_target.c
parenta396e20ad0da42b9cf64c39a99034523d819f008 (diff)
downloadpostgresql-e0e492e5a928e9c9eda01eeebadcfc36f9f8e7b7.tar.gz
postgresql-e0e492e5a928e9c9eda01eeebadcfc36f9f8e7b7.zip
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
Diffstat (limited to 'src/backend/parser/parse_target.c')
-rw-r--r--src/backend/parser/parse_target.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 57247de363b..3bc62ac3ba5 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -1499,7 +1499,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)
@@ -1587,10 +1588,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 = {0};
+ Index levelsup;
+ /* 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 */
@@ -1641,12 +1649,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;