diff options
Diffstat (limited to 'src/backend/nodes')
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/makefuncs.c | 32 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 1 |
5 files changed, 39 insertions, 2 deletions
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index bcc6496a952..71e305804db 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -509,6 +509,7 @@ _copyFunctionScan(const FunctionScan *from) COPY_NODE_FIELD(funccoltypes); COPY_NODE_FIELD(funccoltypmods); COPY_NODE_FIELD(funccolcollations); + COPY_SCALAR_FIELD(funcordinality); return newnode; } @@ -1983,6 +1984,7 @@ _copyRangeTblEntry(const RangeTblEntry *from) COPY_NODE_FIELD(funccoltypes); COPY_NODE_FIELD(funccoltypmods); COPY_NODE_FIELD(funccolcollations); + COPY_SCALAR_FIELD(funcordinality); COPY_NODE_FIELD(values_lists); COPY_NODE_FIELD(values_collations); COPY_STRING_FIELD(ctename); @@ -2296,6 +2298,7 @@ _copyRangeFunction(const RangeFunction *from) { RangeFunction *newnode = makeNode(RangeFunction); + COPY_SCALAR_FIELD(ordinality); COPY_SCALAR_FIELD(lateral); COPY_NODE_FIELD(funccallnode); COPY_NODE_FIELD(alias); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 7f9737ee8e8..3183ccff4d3 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -2126,6 +2126,7 @@ _equalRangeSubselect(const RangeSubselect *a, const RangeSubselect *b) static bool _equalRangeFunction(const RangeFunction *a, const RangeFunction *b) { + COMPARE_SCALAR_FIELD(ordinality); COMPARE_SCALAR_FIELD(lateral); COMPARE_NODE_FIELD(funccallnode); COMPARE_NODE_FIELD(alias); @@ -2234,6 +2235,7 @@ _equalRangeTblEntry(const RangeTblEntry *a, const RangeTblEntry *b) COMPARE_NODE_FIELD(funccoltypes); COMPARE_NODE_FIELD(funccoltypmods); COMPARE_NODE_FIELD(funccolcollations); + COMPARE_SCALAR_FIELD(funcordinality); COMPARE_NODE_FIELD(values_lists); COMPARE_NODE_FIELD(values_collations); COMPARE_STRING_FIELD(ctename); diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 0f8a282ec81..b742ec95324 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -126,6 +126,10 @@ makeVarFromTargetEntry(Index varno, * returning a non-composite result type, we produce a normal Var referencing * the function's result directly, instead of the single-column composite * value that the whole-row notation might otherwise suggest. + * + * We also handle the specific case of function RTEs with ordinality, + * where the additional column has to be added. This forces the result + * to be composite and RECORD type. */ Var * makeWholeRowVar(RangeTblEntry *rte, @@ -151,9 +155,33 @@ makeWholeRowVar(RangeTblEntry *rte, InvalidOid, varlevelsup); break; + case RTE_FUNCTION: + /* + * RTE is a function with or without ordinality. We map the + * cases as follows: + * + * If ordinality is set, we return a composite var even if + * the function is a scalar. This var is always of RECORD type. + * + * If ordinality is not set but the function returns a row, + * we keep the function's return type. + * + * If the function is a scalar, we do what allowScalar requests. + */ toid = exprType(rte->funcexpr); - if (type_is_rowtype(toid)) + + if (rte->funcordinality) + { + /* ORDINALITY always produces an anonymous RECORD result */ + result = makeVar(varno, + InvalidAttrNumber, + RECORDOID, + -1, + InvalidOid, + varlevelsup); + } + else if (type_is_rowtype(toid)) { /* func returns composite; same as relation case */ result = makeVar(varno, @@ -184,8 +212,8 @@ makeWholeRowVar(RangeTblEntry *rte, varlevelsup); } break; - default: + default: /* * RTE is a join, subselect, or VALUES. We represent this as a * whole-row Var of RECORD type. (Note that in most cases the Var diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 48cd9dcb8d4..bad22399bf8 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -521,6 +521,7 @@ _outFunctionScan(StringInfo str, const FunctionScan *node) WRITE_NODE_FIELD(funccoltypes); WRITE_NODE_FIELD(funccoltypmods); WRITE_NODE_FIELD(funccolcollations); + WRITE_BOOL_FIELD(funcordinality); } static void @@ -2382,6 +2383,7 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) WRITE_NODE_FIELD(funccoltypes); WRITE_NODE_FIELD(funccoltypmods); WRITE_NODE_FIELD(funccolcollations); + WRITE_BOOL_FIELD(funcordinality); break; case RTE_VALUES: WRITE_NODE_FIELD(values_lists); @@ -2614,6 +2616,7 @@ _outRangeFunction(StringInfo str, const RangeFunction *node) { WRITE_NODE_TYPE("RANGEFUNCTION"); + WRITE_BOOL_FIELD(ordinality); WRITE_BOOL_FIELD(lateral); WRITE_NODE_FIELD(funccallnode); WRITE_NODE_FIELD(alias); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index dc9cb3ebd2c..aad63e58cfd 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1223,6 +1223,7 @@ _readRangeTblEntry(void) READ_NODE_FIELD(funccoltypes); READ_NODE_FIELD(funccoltypmods); READ_NODE_FIELD(funccolcollations); + READ_BOOL_FIELD(funcordinality); break; case RTE_VALUES: READ_NODE_FIELD(values_lists); |