Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)