@@ -2014,31 +2014,40 @@ addRangeTableEntryForENR(ParseState *pstate,
2014
2014
2015
2015
/*
2016
2016
* 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.
2018
2018
*/
2019
2019
tupdesc = ENRMetadataGetTupDesc (enrmd );
2020
2020
rte -> eref = makeAlias (refname , NIL );
2021
2021
buildRelationAliases (tupdesc , alias , rte -> eref );
2022
+
2023
+ /* Record additional data for ENR, including column type info */
2022
2024
rte -> enrname = enrmd -> name ;
2023
2025
rte -> enrtuples = enrmd -> enrtuples ;
2024
2026
rte -> coltypes = NIL ;
2025
2027
rte -> coltypmods = NIL ;
2026
2028
rte -> colcollations = NIL ;
2027
2029
for (attno = 1 ; attno <= tupdesc -> natts ; ++ attno )
2028
2030
{
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
+ }
2042
2051
}
2043
2052
2044
2053
/*
@@ -2417,7 +2426,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
2417
2426
case RTE_CTE :
2418
2427
case RTE_NAMEDTUPLESTORE :
2419
2428
{
2420
- /* Tablefunc, Values or CTE RTE */
2429
+ /* Tablefunc, Values, CTE, or ENR RTE */
2421
2430
ListCell * aliasp_item = list_head (rte -> eref -> colnames );
2422
2431
ListCell * lct ;
2423
2432
ListCell * lcm ;
@@ -2437,23 +2446,43 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
2437
2446
if (colnames )
2438
2447
{
2439
2448
/* 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 ("" )));
2441
2459
2442
- * colnames = lappend (* colnames ,
2443
- makeString (pstrdup (label )));
2444
2460
aliasp_item = lnext (aliasp_item );
2445
2461
}
2446
2462
2447
2463
if (colvars )
2448
2464
{
2449
- Var * varnode ;
2465
+ if (OidIsValid (coltype ))
2466
+ {
2467
+ Var * varnode ;
2450
2468
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 ;
2455
2473
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
+ }
2457
2486
}
2458
2487
}
2459
2488
}
@@ -2832,13 +2861,21 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
2832
2861
case RTE_NAMEDTUPLESTORE :
2833
2862
{
2834
2863
/*
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
2837
2866
*/
2838
2867
Assert (attnum > 0 && attnum <= list_length (rte -> coltypes ));
2839
2868
* vartype = list_nth_oid (rte -> coltypes , attnum - 1 );
2840
2869
* vartypmod = list_nth_int (rte -> coltypmods , attnum - 1 );
2841
2870
* 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 )));
2842
2879
}
2843
2880
break ;
2844
2881
default :
@@ -2889,15 +2926,11 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
2889
2926
break ;
2890
2927
case RTE_NAMEDTUPLESTORE :
2891
2928
{
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 )));
2901
2934
}
2902
2935
break ;
2903
2936
case RTE_JOIN :
0 commit comments