Skip to content

Commit 8689e38

Browse files
committed
Clean up handling of dropped columns in NAMEDTUPLESTORE RTEs.
The NAMEDTUPLESTORE patch piggybacked on the infrastructure for TABLEFUNC/VALUES/CTE RTEs, none of which can ever have dropped columns, so the possibility was ignored most places. Fix that, including adding a specification to parsenodes.h about what it's supposed to look like. In passing, clean up assorted comments that hadn't been maintained properly by said patch. Per bug #14799 from Philippe Beaudoin. Back-patch to v10. Discussion: https://postgr.es/m/20170906120005.25630.84360@wrigleys.postgresql.org
1 parent 0b554e4 commit 8689e38

File tree

5 files changed

+77
-38
lines changed

5 files changed

+77
-38
lines changed

src/backend/optimizer/util/relnode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
178178
case RTE_NAMEDTUPLESTORE:
179179

180180
/*
181-
* Subquery, function, tablefunc, or values list --- set up attr
182-
* range and arrays
181+
* Subquery, function, tablefunc, values list, CTE, or ENR --- set
182+
* up attr range and arrays
183183
*
184184
* Note: 0 is included in range to support whole-row Vars
185185
*/

src/backend/parser/parse_relation.c

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,11 +2014,13 @@ addRangeTableEntryForENR(ParseState *pstate,
20142014

20152015
/*
20162016
* Build the list of effective column names using user-supplied aliases
2017-
* and/or actual column names. Also build the cannibalized fields.
2017+
* and/or actual column names.
20182018
*/
20192019
tupdesc = ENRMetadataGetTupDesc(enrmd);
20202020
rte->eref = makeAlias(refname, NIL);
20212021
buildRelationAliases(tupdesc, alias, rte->eref);
2022+
2023+
/* Record additional data for ENR, including column type info */
20222024
rte->enrname = enrmd->name;
20232025
rte->enrtuples = enrmd->enrtuples;
20242026
rte->coltypes = NIL;
@@ -2028,16 +2030,24 @@ addRangeTableEntryForENR(ParseState *pstate,
20282030
{
20292031
Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
20302032

2031-
if (att->atttypid == InvalidOid &&
2032-
!(att->attisdropped))
2033-
elog(ERROR, "atttypid was invalid for column which has not been dropped from \"%s\"",
2034-
rv->relname);
2035-
rte->coltypes =
2036-
lappend_oid(rte->coltypes, att->atttypid);
2037-
rte->coltypmods =
2038-
lappend_int(rte->coltypmods, att->atttypmod);
2039-
rte->colcollations =
2040-
lappend_oid(rte->colcollations, att->attcollation);
2033+
if (att->attisdropped)
2034+
{
2035+
/* Record zeroes for a dropped column */
2036+
rte->coltypes = lappend_oid(rte->coltypes, InvalidOid);
2037+
rte->coltypmods = lappend_int(rte->coltypmods, 0);
2038+
rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
2039+
}
2040+
else
2041+
{
2042+
/* Let's just make sure we can tell this isn't dropped */
2043+
if (att->atttypid == InvalidOid)
2044+
elog(ERROR, "atttypid is invalid for non-dropped column in \"%s\"",
2045+
rv->relname);
2046+
rte->coltypes = lappend_oid(rte->coltypes, att->atttypid);
2047+
rte->coltypmods = lappend_int(rte->coltypmods, att->atttypmod);
2048+
rte->colcollations = lappend_oid(rte->colcollations,
2049+
att->attcollation);
2050+
}
20412051
}
20422052

20432053
/*
@@ -2416,7 +2426,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
24162426
case RTE_CTE:
24172427
case RTE_NAMEDTUPLESTORE:
24182428
{
2419-
/* Tablefunc, Values or CTE RTE */
2429+
/* Tablefunc, Values, CTE, or ENR RTE */
24202430
ListCell *aliasp_item = list_head(rte->eref->colnames);
24212431
ListCell *lct;
24222432
ListCell *lcm;
@@ -2436,23 +2446,43 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
24362446
if (colnames)
24372447
{
24382448
/* Assume there is one alias per output column */
2439-
char *label = strVal(lfirst(aliasp_item));
2449+
if (OidIsValid(coltype))
2450+
{
2451+
char *label = strVal(lfirst(aliasp_item));
2452+
2453+
*colnames = lappend(*colnames,
2454+
makeString(pstrdup(label)));
2455+
}
2456+
else if (include_dropped)
2457+
*colnames = lappend(*colnames,
2458+
makeString(pstrdup("")));
24402459

2441-
*colnames = lappend(*colnames,
2442-
makeString(pstrdup(label)));
24432460
aliasp_item = lnext(aliasp_item);
24442461
}
24452462

24462463
if (colvars)
24472464
{
2448-
Var *varnode;
2465+
if (OidIsValid(coltype))
2466+
{
2467+
Var *varnode;
24492468

2450-
varnode = makeVar(rtindex, varattno,
2451-
coltype, coltypmod, colcoll,
2452-
sublevels_up);
2453-
varnode->location = location;
2469+
varnode = makeVar(rtindex, varattno,
2470+
coltype, coltypmod, colcoll,
2471+
sublevels_up);
2472+
varnode->location = location;
24542473

2455-
*colvars = lappend(*colvars, varnode);
2474+
*colvars = lappend(*colvars, varnode);
2475+
}
2476+
else if (include_dropped)
2477+
{
2478+
/*
2479+
* It doesn't really matter what type the Const
2480+
* claims to be.
2481+
*/
2482+
*colvars = lappend(*colvars,
2483+
makeNullConst(INT4OID, -1,
2484+
InvalidOid));
2485+
}
24562486
}
24572487
}
24582488
}
@@ -2831,13 +2861,21 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
28312861
case RTE_NAMEDTUPLESTORE:
28322862
{
28332863
/*
2834-
* tablefunc, VALUES or CTE RTE --- get type info from lists
2835-
* in the RTE
2864+
* tablefunc, VALUES, CTE, or ENR RTE --- get type info from
2865+
* lists in the RTE
28362866
*/
28372867
Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
28382868
*vartype = list_nth_oid(rte->coltypes, attnum - 1);
28392869
*vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
28402870
*varcollid = list_nth_oid(rte->colcollations, attnum - 1);
2871+
2872+
/* For ENR, better check for dropped column */
2873+
if (!OidIsValid(*vartype))
2874+
ereport(ERROR,
2875+
(errcode(ERRCODE_UNDEFINED_COLUMN),
2876+
errmsg("column %d of relation \"%s\" does not exist",
2877+
attnum,
2878+
rte->eref->aliasname)));
28412879
}
28422880
break;
28432881
default:
@@ -2888,15 +2926,11 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
28882926
break;
28892927
case RTE_NAMEDTUPLESTORE:
28902928
{
2891-
Assert(rte->enrname);
2892-
2893-
/*
2894-
* We checked when we loaded coltypes for the tuplestore that
2895-
* InvalidOid was only used for dropped columns, so it is safe
2896-
* to count on that here.
2897-
*/
2898-
result =
2899-
((list_nth_oid(rte->coltypes, attnum - 1) == InvalidOid));
2929+
/* Check dropped-ness by testing for valid coltype */
2930+
if (attnum <= 0 ||
2931+
attnum > list_length(rte->coltypes))
2932+
elog(ERROR, "invalid varattno %d", attnum);
2933+
result = !OidIsValid((list_nth_oid(rte->coltypes, attnum - 1)));
29002934
}
29012935
break;
29022936
case RTE_JOIN:

src/backend/parser/parse_target.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,8 +1511,8 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
15111511
case RTE_NAMEDTUPLESTORE:
15121512

15131513
/*
1514-
* This case should not occur: a column of a table or values list
1515-
* shouldn't have type RECORD. Fall through and fail (most
1514+
* This case should not occur: a column of a table, values list,
1515+
* or ENR shouldn't have type RECORD. Fall through and fail (most
15161516
* likely) at the bottom.
15171517
*/
15181518
break;

src/backend/utils/adt/ruleutils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6846,8 +6846,8 @@ get_name_for_var_field(Var *var, int fieldno,
68466846
case RTE_NAMEDTUPLESTORE:
68476847

68486848
/*
6849-
* This case should not occur: a column of a table or values list
6850-
* shouldn't have type RECORD. Fall through and fail (most
6849+
* This case should not occur: a column of a table, values list,
6850+
* or ENR shouldn't have type RECORD. Fall through and fail (most
68516851
* likely) at the bottom.
68526852
*/
68536853
break;

src/include/nodes/parsenodes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,11 @@ typedef struct RangeTblEntry
10251025
* from the catalogs if 'relid' was supplied, but we'd still need these
10261026
* for TupleDesc-based ENRs, so we might as well always store the type
10271027
* info here).
1028+
*
1029+
* For ENRs only, we have to consider the possibility of dropped columns.
1030+
* A dropped column is included in these lists, but it will have zeroes in
1031+
* all three lists (as well as an empty-string entry in eref). Testing
1032+
* for zero coltype is the standard way to detect a dropped column.
10281033
*/
10291034
List *coltypes; /* OID list of column type OIDs */
10301035
List *coltypmods; /* integer list of column typmods */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy