Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4838829

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 3fbf095 commit 4838829

File tree

5 files changed

+79
-41
lines changed

5 files changed

+79
-41
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: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,31 +2014,40 @@ 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;
20252027
rte->coltypmods = NIL;
20262028
rte->colcollations = NIL;
20272029
for (attno = 1; attno <= tupdesc->natts; ++attno)
20282030
{
2029-
if (tupdesc->attrs[attno - 1]->atttypid == InvalidOid &&
2030-
!(tupdesc->attrs[attno - 1]->attisdropped))
2031-
elog(ERROR, "atttypid was invalid for column which has not been dropped from \"%s\"",
2032-
rv->relname);
2033-
rte->coltypes =
2034-
lappend_oid(rte->coltypes,
2035-
tupdesc->attrs[attno - 1]->atttypid);
2036-
rte->coltypmods =
2037-
lappend_int(rte->coltypmods,
2038-
tupdesc->attrs[attno - 1]->atttypmod);
2039-
rte->colcollations =
2040-
lappend_oid(rte->colcollations,
2041-
tupdesc->attrs[attno - 1]->attcollation);
2031+
Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
2032+
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+
}
20422051
}
20432052

20442053
/*
@@ -2417,7 +2426,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
24172426
case RTE_CTE:
24182427
case RTE_NAMEDTUPLESTORE:
24192428
{
2420-
/* Tablefunc, Values or CTE RTE */
2429+
/* Tablefunc, Values, CTE, or ENR RTE */
24212430
ListCell *aliasp_item = list_head(rte->eref->colnames);
24222431
ListCell *lct;
24232432
ListCell *lcm;
@@ -2437,23 +2446,43 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
24372446
if (colnames)
24382447
{
24392448
/* Assume there is one alias per output column */
2440-
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("")));
24412459

2442-
*colnames = lappend(*colnames,
2443-
makeString(pstrdup(label)));
24442460
aliasp_item = lnext(aliasp_item);
24452461
}
24462462

24472463
if (colvars)
24482464
{
2449-
Var *varnode;
2465+
if (OidIsValid(coltype))
2466+
{
2467+
Var *varnode;
24502468

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

2456-
*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+
}
24572486
}
24582487
}
24592488
}
@@ -2832,13 +2861,21 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
28322861
case RTE_NAMEDTUPLESTORE:
28332862
{
28342863
/*
2835-
* tablefunc, VALUES or CTE RTE --- get type info from lists
2836-
* in the RTE
2864+
* tablefunc, VALUES, CTE, or ENR RTE --- get type info from
2865+
* lists in the RTE
28372866
*/
28382867
Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
28392868
*vartype = list_nth_oid(rte->coltypes, attnum - 1);
28402869
*vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
28412870
*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)));
28422879
}
28432880
break;
28442881
default:
@@ -2889,15 +2926,11 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
28892926
break;
28902927
case RTE_NAMEDTUPLESTORE:
28912928
{
2892-
Assert(rte->enrname);
2893-
2894-
/*
2895-
* We checked when we loaded coltypes for the tuplestore that
2896-
* InvalidOid was only used for dropped columns, so it is safe
2897-
* to count on that here.
2898-
*/
2899-
result =
2900-
((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)));
29012934
}
29022935
break;
29032936
case RTE_JOIN:

src/backend/parser/parse_target.c

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

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

src/backend/utils/adt/ruleutils.c

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

68466846
/*
6847-
* This case should not occur: a column of a table or values list
6848-
* shouldn't have type RECORD. Fall through and fail (most
6847+
* This case should not occur: a column of a table, values list,
6848+
* or ENR shouldn't have type RECORD. Fall through and fail (most
68496849
* likely) at the bottom.
68506850
*/
68516851
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)