Commit 53685d79 authored by Noah Misch's avatar Noah Misch

Rename TABLE() to ROWS FROM().

SQL-standard TABLE() is a subset of UNNEST(); they deal with arrays and
other collection types.  This feature, however, deals with set-returning
functions.  Use a different syntax for this feature to keep open the
possibility of implementing the standard TABLE().
parent 01cc1fec
...@@ -647,7 +647,7 @@ FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow')) ...@@ -647,7 +647,7 @@ FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow'))
</para> </para>
<para> <para>
Table functions may also be combined using the <literal>TABLE</literal> Table functions may also be combined using the <literal>ROWS FROM</>
syntax, with the results returned in parallel columns; the number of syntax, with the results returned in parallel columns; the number of
result rows in this case is that of the largest function result, with result rows in this case is that of the largest function result, with
smaller results padded with NULLs to match. smaller results padded with NULLs to match.
...@@ -655,7 +655,7 @@ FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow')) ...@@ -655,7 +655,7 @@ FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow'))
<synopsis> <synopsis>
<replaceable>function_call</replaceable> <optional>WITH ORDINALITY</optional> <optional><optional>AS</optional> <replaceable>table_alias</replaceable> <optional>(<replaceable>column_alias</replaceable> <optional>, ... </optional>)</optional></optional> <replaceable>function_call</replaceable> <optional>WITH ORDINALITY</optional> <optional><optional>AS</optional> <replaceable>table_alias</replaceable> <optional>(<replaceable>column_alias</replaceable> <optional>, ... </optional>)</optional></optional>
TABLE( <replaceable>function_call</replaceable> <optional>, ... </optional> ) <optional>WITH ORDINALITY</optional> <optional><optional>AS</optional> <replaceable>table_alias</replaceable> <optional>(<replaceable>column_alias</replaceable> <optional>, ... </optional>)</optional></optional> ROWS FROM( <replaceable>function_call</replaceable> <optional>, ... </optional> ) <optional>WITH ORDINALITY</optional> <optional><optional>AS</optional> <replaceable>table_alias</replaceable> <optional>(<replaceable>column_alias</replaceable> <optional>, ... </optional>)</optional></optional>
</synopsis> </synopsis>
<para> <para>
...@@ -674,7 +674,7 @@ TABLE( <replaceable>function_call</replaceable> <optional>, ... </optional> ) <o ...@@ -674,7 +674,7 @@ TABLE( <replaceable>function_call</replaceable> <optional>, ... </optional> ) <o
any number of array parameters, and it returns a corresponding number of any number of array parameters, and it returns a corresponding number of
columns, as if <literal>UNNEST</literal> columns, as if <literal>UNNEST</literal>
(<xref linkend="functions-array">) had been called on each parameter (<xref linkend="functions-array">) had been called on each parameter
separately and combined using the <literal>TABLE</literal> construct. separately and combined using the <literal>ROWS FROM</literal> construct.
</para> </para>
<synopsis> <synopsis>
...@@ -683,7 +683,7 @@ UNNEST( <replaceable>array_expression</replaceable> <optional>, ... </optional> ...@@ -683,7 +683,7 @@ UNNEST( <replaceable>array_expression</replaceable> <optional>, ... </optional>
<para> <para>
If no <replaceable>table_alias</replaceable> is specified, the function If no <replaceable>table_alias</replaceable> is specified, the function
name is used as the table name; in the case of a <literal>TABLE()</> name is used as the table name; in the case of a <literal>ROWS FROM()</>
construct, the first function's name is used. construct, the first function's name is used.
</para> </para>
...@@ -731,20 +731,20 @@ SELECT * FROM vw_getfoo; ...@@ -731,20 +731,20 @@ SELECT * FROM vw_getfoo;
<synopsis> <synopsis>
<replaceable>function_call</replaceable> <optional>AS</optional> <replaceable>alias</replaceable> (<replaceable>column_definition</replaceable> <optional>, ... </optional>) <replaceable>function_call</replaceable> <optional>AS</optional> <replaceable>alias</replaceable> (<replaceable>column_definition</replaceable> <optional>, ... </optional>)
<replaceable>function_call</replaceable> AS <optional><replaceable>alias</replaceable></optional> (<replaceable>column_definition</replaceable> <optional>, ... </optional>) <replaceable>function_call</replaceable> AS <optional><replaceable>alias</replaceable></optional> (<replaceable>column_definition</replaceable> <optional>, ... </optional>)
TABLE( ... <replaceable>function_call</replaceable> AS (<replaceable>column_definition</replaceable> <optional>, ... </optional>) <optional>, ... </optional> ) ROWS FROM( ... <replaceable>function_call</replaceable> AS (<replaceable>column_definition</replaceable> <optional>, ... </optional>) <optional>, ... </optional> )
</synopsis> </synopsis>
<para> <para>
When not using the <literal>TABLE()</> syntax, When not using the <literal>ROWS FROM()</> syntax,
the <replaceable>column_definition</replaceable> list replaces the column the <replaceable>column_definition</replaceable> list replaces the column
alias list that could otherwise be attached to the <literal>FROM</> alias list that could otherwise be attached to the <literal>FROM</>
item; the names in the column definitions serve as column aliases. item; the names in the column definitions serve as column aliases.
When using the <literal>TABLE()</> syntax, When using the <literal>ROWS FROM()</> syntax,
a <replaceable>column_definition</replaceable> list can be attached to a <replaceable>column_definition</replaceable> list can be attached to
each member function separately; or if there is only one member function each member function separately; or if there is only one member function
and no <literal>WITH ORDINALITY</> clause, and no <literal>WITH ORDINALITY</> clause,
a <replaceable>column_definition</replaceable> list can be written in a <replaceable>column_definition</replaceable> list can be written in
place of a column alias list following <literal>TABLE()</>. place of a column alias list following <literal>ROWS FROM()</>.
</para> </para>
<para> <para>
......
...@@ -56,7 +56,7 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replac ...@@ -56,7 +56,7 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replac
[ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ] [ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
[ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] <replaceable class="parameter">alias</replaceable> ( <replaceable class="parameter">column_definition</replaceable> [, ...] ) [ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] <replaceable class="parameter">alias</replaceable> ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
[ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] ) [ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
[ LATERAL ] TABLE( <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] ) ] [, ...] ) [ LATERAL ] ROWS FROM( <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] ) ] [, ...] )
[ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ] [ WITH ORDINALITY ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
<replaceable class="parameter">from_item</replaceable> [ NATURAL ] <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> [ ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) ] <replaceable class="parameter">from_item</replaceable> [ NATURAL ] <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> [ ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) ]
...@@ -390,7 +390,7 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] ...@@ -390,7 +390,7 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
<para> <para>
Multiple function calls can be combined into a Multiple function calls can be combined into a
single <literal>FROM</>-clause item by surrounding them single <literal>FROM</>-clause item by surrounding them
with <literal>TABLE( ... )</>. The output of such an item is the with <literal>ROWS FROM( ... )</>. The output of such an item is the
concatenation of the first row from each function, then the second concatenation of the first row from each function, then the second
row from each function, etc. If some of the functions produce fewer row from each function, etc. If some of the functions produce fewer
rows than others, NULLs are substituted for the missing data, so rows than others, NULLs are substituted for the missing data, so
...@@ -410,18 +410,18 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] ...@@ -410,18 +410,18 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
</para> </para>
<para> <para>
When using the <literal>TABLE( ... )</> syntax, if one of the When using the <literal>ROWS FROM( ... )</> syntax, if one of the
functions requires a column definition list, it's preferred to put functions requires a column definition list, it's preferred to put
the column definition list after the function call inside the column definition list after the function call inside
<literal>TABLE( ... )</>. A column definition list can be placed <literal>ROWS FROM( ... )</>. A column definition list can be placed
after the <literal>TABLE( ... )</> construct only if there's just a after the <literal>ROWS FROM( ... )</> construct only if there's just
single function and no <literal>WITH ORDINALITY</> clause. a single function and no <literal>WITH ORDINALITY</> clause.
</para> </para>
<para> <para>
To use <literal>ORDINALITY</literal> together with a column definition To use <literal>ORDINALITY</literal> together with a column definition
list, you must use the <literal>TABLE( ... )</> syntax and put the list, you must use the <literal>ROWS FROM( ... )</> syntax and put the
column definition list inside <literal>TABLE( ... )</>. column definition list inside <literal>ROWS FROM( ... )</>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -1811,8 +1811,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward'; ...@@ -1811,8 +1811,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
</para> </para>
<para> <para>
Placing multiple function calls inside <literal>TABLE( ... )</> syntax is <literal>ROWS FROM( ... )</> is an extension of the SQL standard.
also an extension of the SQL standard.
</para> </para>
</refsect2> </refsect2>
......
...@@ -2310,7 +2310,7 @@ _copyRangeFunction(const RangeFunction *from) ...@@ -2310,7 +2310,7 @@ _copyRangeFunction(const RangeFunction *from)
COPY_SCALAR_FIELD(lateral); COPY_SCALAR_FIELD(lateral);
COPY_SCALAR_FIELD(ordinality); COPY_SCALAR_FIELD(ordinality);
COPY_SCALAR_FIELD(is_table); COPY_SCALAR_FIELD(is_rowsfrom);
COPY_NODE_FIELD(functions); COPY_NODE_FIELD(functions);
COPY_NODE_FIELD(alias); COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(coldeflist); COPY_NODE_FIELD(coldeflist);
......
...@@ -2142,7 +2142,7 @@ _equalRangeFunction(const RangeFunction *a, const RangeFunction *b) ...@@ -2142,7 +2142,7 @@ _equalRangeFunction(const RangeFunction *a, const RangeFunction *b)
{ {
COMPARE_SCALAR_FIELD(lateral); COMPARE_SCALAR_FIELD(lateral);
COMPARE_SCALAR_FIELD(ordinality); COMPARE_SCALAR_FIELD(ordinality);
COMPARE_SCALAR_FIELD(is_table); COMPARE_SCALAR_FIELD(is_rowsfrom);
COMPARE_NODE_FIELD(functions); COMPARE_NODE_FIELD(functions);
COMPARE_NODE_FIELD(alias); COMPARE_NODE_FIELD(alias);
COMPARE_NODE_FIELD(coldeflist); COMPARE_NODE_FIELD(coldeflist);
......
...@@ -2629,7 +2629,7 @@ _outRangeFunction(StringInfo str, const RangeFunction *node) ...@@ -2629,7 +2629,7 @@ _outRangeFunction(StringInfo str, const RangeFunction *node)
WRITE_BOOL_FIELD(lateral); WRITE_BOOL_FIELD(lateral);
WRITE_BOOL_FIELD(ordinality); WRITE_BOOL_FIELD(ordinality);
WRITE_BOOL_FIELD(is_table); WRITE_BOOL_FIELD(is_rowsfrom);
WRITE_NODE_FIELD(functions); WRITE_NODE_FIELD(functions);
WRITE_NODE_FIELD(alias); WRITE_NODE_FIELD(alias);
WRITE_NODE_FIELD(coldeflist); WRITE_NODE_FIELD(coldeflist);
......
...@@ -406,7 +406,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); ...@@ -406,7 +406,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
a_expr b_expr c_expr AexprConst indirection_el a_expr b_expr c_expr AexprConst indirection_el
columnref in_expr having_clause func_table array_expr columnref in_expr having_clause func_table array_expr
ExclusionWhereClause ExclusionWhereClause
%type <list> func_table_item func_table_list opt_col_def_list %type <list> rowsfrom_item rowsfrom_list opt_col_def_list
%type <boolean> opt_ordinality %type <boolean> opt_ordinality
%type <list> ExclusionConstraintList ExclusionConstraintElem %type <list> ExclusionConstraintList ExclusionConstraintElem
%type <list> func_arg_list %type <list> func_arg_list
...@@ -9980,13 +9980,13 @@ relation_expr_opt_alias: relation_expr %prec UMINUS ...@@ -9980,13 +9980,13 @@ relation_expr_opt_alias: relation_expr %prec UMINUS
/* /*
* func_table represents a function invocation in a FROM list. It can be * func_table represents a function invocation in a FROM list. It can be
* a plain function call, like "foo(...)", or a TABLE expression with * a plain function call, like "foo(...)", or a ROWS FROM expression with
* one or more function calls, "TABLE (foo(...), bar(...))", * one or more function calls, "ROWS FROM (foo(...), bar(...))",
* optionally with WITH ORDINALITY attached. * optionally with WITH ORDINALITY attached.
* In the TABLE syntax, a column definition list can be given for each * In the ROWS FROM syntax, a column definition list can be given for each
* function, for example: * function, for example:
* TABLE (foo() AS (foo_res_a text, foo_res_b text), * ROWS FROM (foo() AS (foo_res_a text, foo_res_b text),
* bar() AS (bar_res_a text, bar_res_b text)) * bar() AS (bar_res_a text, bar_res_b text))
* It's also possible to attach a column definition list to the RangeFunction * It's also possible to attach a column definition list to the RangeFunction
* as a whole, but that's handled by the table_ref production. * as a whole, but that's handled by the table_ref production.
*/ */
...@@ -9995,29 +9995,30 @@ func_table: func_expr_windowless opt_ordinality ...@@ -9995,29 +9995,30 @@ func_table: func_expr_windowless opt_ordinality
RangeFunction *n = makeNode(RangeFunction); RangeFunction *n = makeNode(RangeFunction);
n->lateral = false; n->lateral = false;
n->ordinality = $2; n->ordinality = $2;
n->is_table = false; n->is_rowsfrom = false;
n->functions = list_make1(list_make2($1, NIL)); n->functions = list_make1(list_make2($1, NIL));
/* alias and coldeflist are set by table_ref production */ /* alias and coldeflist are set by table_ref production */
$$ = (Node *) n; $$ = (Node *) n;
} }
| TABLE '(' func_table_list ')' opt_ordinality | ROWS FROM '(' rowsfrom_list ')' opt_ordinality
{ {
RangeFunction *n = makeNode(RangeFunction); RangeFunction *n = makeNode(RangeFunction);
n->lateral = false; n->lateral = false;
n->ordinality = $5; n->ordinality = $6;
n->is_table = true; n->is_rowsfrom = true;
n->functions = $3; n->functions = $4;
/* alias and coldeflist are set by table_ref production */ /* alias and coldeflist are set by table_ref production */
$$ = (Node *) n; $$ = (Node *) n;
} }
; ;
func_table_item: func_expr_windowless opt_col_def_list rowsfrom_item: func_expr_windowless opt_col_def_list
{ $$ = list_make2($1, $2); } { $$ = list_make2($1, $2); }
; ;
func_table_list: func_table_item { $$ = list_make1($1); } rowsfrom_list:
| func_table_list ',' func_table_item { $$ = lappend($1, $3); } rowsfrom_item { $$ = list_make1($1); }
| rowsfrom_list ',' rowsfrom_item { $$ = lappend($1, $3); }
; ;
opt_col_def_list: AS '(' TableFuncElementList ')' { $$ = $3; } opt_col_def_list: AS '(' TableFuncElementList ')' { $$ = $3; }
......
...@@ -655,25 +655,25 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) ...@@ -655,25 +655,25 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
* expansion) and no WITH ORDINALITY. The reason for the latter * expansion) and no WITH ORDINALITY. The reason for the latter
* restriction is that it's not real clear whether the ordinality column * restriction is that it's not real clear whether the ordinality column
* should be in the coldeflist, and users are too likely to make mistakes * should be in the coldeflist, and users are too likely to make mistakes
* in one direction or the other. Putting the coldeflist inside TABLE() * in one direction or the other. Putting the coldeflist inside ROWS
* is much clearer in this case. * FROM() is much clearer in this case.
*/ */
if (r->coldeflist) if (r->coldeflist)
{ {
if (list_length(funcexprs) != 1) if (list_length(funcexprs) != 1)
{ {
if (r->is_table) if (r->is_rowsfrom)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("TABLE() with multiple functions cannot have a column definition list"), errmsg("ROWS FROM() with multiple functions cannot have a column definition list"),
errhint("Put a separate column definition list for each function inside TABLE()."), errhint("Put a separate column definition list for each function inside ROWS FROM()."),
parser_errposition(pstate, parser_errposition(pstate,
exprLocation((Node *) r->coldeflist)))); exprLocation((Node *) r->coldeflist))));
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("UNNEST() with multiple arguments cannot have a column definition list"), errmsg("UNNEST() with multiple arguments cannot have a column definition list"),
errhint("Use separate UNNEST() calls inside TABLE(), and attach a column definition list to each one."), errhint("Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one."),
parser_errposition(pstate, parser_errposition(pstate,
exprLocation((Node *) r->coldeflist)))); exprLocation((Node *) r->coldeflist))));
} }
...@@ -681,7 +681,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) ...@@ -681,7 +681,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("WITH ORDINALITY cannot be used with a column definition list"), errmsg("WITH ORDINALITY cannot be used with a column definition list"),
errhint("Put the column definition list inside TABLE()."), errhint("Put the column definition list inside ROWS FROM()."),
parser_errposition(pstate, parser_errposition(pstate,
exprLocation((Node *) r->coldeflist)))); exprLocation((Node *) r->coldeflist))));
......
...@@ -8125,10 +8125,10 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) ...@@ -8125,10 +8125,10 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
rtfunc1 = (RangeTblFunction *) linitial(rte->functions); rtfunc1 = (RangeTblFunction *) linitial(rte->functions);
/* /*
* Omit TABLE() syntax if there's just one function, unless it * Omit ROWS FROM() syntax for just one function, unless it
* has both a coldeflist and WITH ORDINALITY. If it has both, * has both a coldeflist and WITH ORDINALITY. If it has both,
* we must use TABLE() syntax to avoid ambiguity about whether * we must use ROWS FROM() syntax to avoid ambiguity about
* the coldeflist includes the ordinality column. * whether the coldeflist includes the ordinality column.
*/ */
if (list_length(rte->functions) == 1 && if (list_length(rte->functions) == 1 &&
(rtfunc1->funccolnames == NIL || !rte->funcordinality)) (rtfunc1->funccolnames == NIL || !rte->funcordinality))
...@@ -8151,8 +8151,8 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) ...@@ -8151,8 +8151,8 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
* XXX This is pretty ugly, since it makes not-terribly- * XXX This is pretty ugly, since it makes not-terribly-
* future-proof assumptions about what the parser would do * future-proof assumptions about what the parser would do
* with the output; but the alternative is to emit our * with the output; but the alternative is to emit our
* nonstandard extended TABLE() notation for what might * nonstandard ROWS FROM() notation for what might have
* have been a perfectly spec-compliant multi-argument * been a perfectly spec-compliant multi-argument
* UNNEST(). * UNNEST().
*/ */
all_unnest = true; all_unnest = true;
...@@ -8189,7 +8189,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) ...@@ -8189,7 +8189,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
{ {
int funcno = 0; int funcno = 0;
appendStringInfoString(buf, "TABLE("); appendStringInfoString(buf, "ROWS FROM(");
foreach(lc, rte->functions) foreach(lc, rte->functions)
{ {
RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
...@@ -8422,7 +8422,7 @@ get_column_alias_list(deparse_columns *colinfo, deparse_context *context) ...@@ -8422,7 +8422,7 @@ get_column_alias_list(deparse_columns *colinfo, deparse_context *context)
* *
* When printing a top-level coldeflist (which is syntactically also the * When printing a top-level coldeflist (which is syntactically also the
* relation's column alias list), use column names from colinfo. But when * relation's column alias list), use column names from colinfo. But when
* printing a coldeflist embedded inside TABLE(), we prefer to use the * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the
* original coldeflist's names, which are available in rtfunc->funccolnames. * original coldeflist's names, which are available in rtfunc->funccolnames.
* Pass NULL for colinfo to select the latter behavior. * Pass NULL for colinfo to select the latter behavior.
* *
......
...@@ -466,11 +466,11 @@ typedef struct RangeSubselect ...@@ -466,11 +466,11 @@ typedef struct RangeSubselect
* RangeFunction - function call appearing in a FROM clause * RangeFunction - function call appearing in a FROM clause
* *
* functions is a List because we use this to represent the construct * functions is a List because we use this to represent the construct
* TABLE(func1(...), func2(...), ...). Each element of this list is a * ROWS FROM(func1(...), func2(...), ...). Each element of this list is a
* two-element sublist, the first element being the untransformed function * two-element sublist, the first element being the untransformed function
* call tree, and the second element being a possibly-empty list of ColumnDef * call tree, and the second element being a possibly-empty list of ColumnDef
* nodes representing any columndef list attached to that function within the * nodes representing any columndef list attached to that function within the
* TABLE() syntax. * ROWS FROM() syntax.
* *
* alias and coldeflist represent any alias and/or columndef list attached * alias and coldeflist represent any alias and/or columndef list attached
* at the top level. (We disallow coldeflist appearing both here and * at the top level. (We disallow coldeflist appearing both here and
...@@ -481,7 +481,7 @@ typedef struct RangeFunction ...@@ -481,7 +481,7 @@ typedef struct RangeFunction
NodeTag type; NodeTag type;
bool lateral; /* does it have LATERAL prefix? */ bool lateral; /* does it have LATERAL prefix? */
bool ordinality; /* does it have WITH ORDINALITY suffix? */ bool ordinality; /* does it have WITH ORDINALITY suffix? */
bool is_table; /* is result of TABLE() syntax? */ bool is_rowsfrom; /* is result of ROWS FROM() syntax? */
List *functions; /* per-function information, see above */ List *functions; /* per-function information, see above */
Alias *alias; /* table alias & optional column aliases */ Alias *alias; /* table alias & optional column aliases */
List *coldeflist; /* list of ColumnDef nodes to describe result List *coldeflist; /* list of ColumnDef nodes to describe result
......
This diff is collapsed.
...@@ -24,8 +24,8 @@ select definition from pg_views where viewname='vw_ord'; ...@@ -24,8 +24,8 @@ select definition from pg_views where viewname='vw_ord';
drop view vw_ord; drop view vw_ord;
-- multiple functions -- multiple functions
select * from table(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord); select * from rows from(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord);
create temporary view vw_ord as select * from (values (1)) v(n) join table(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord) on (n=ord); create temporary view vw_ord as select * from (values (1)) v(n) join rows from(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord) on (n=ord);
select * from vw_ord; select * from vw_ord;
select definition from pg_views where viewname='vw_ord'; select definition from pg_views where viewname='vw_ord';
drop view vw_ord; drop view vw_ord;
...@@ -33,24 +33,24 @@ drop view vw_ord; ...@@ -33,24 +33,24 @@ drop view vw_ord;
-- expansions of unnest() -- expansions of unnest()
select * from unnest(array[10,20],array['foo','bar'],array[1.0]); select * from unnest(array[10,20],array['foo','bar'],array[1.0]);
select * from unnest(array[10,20],array['foo','bar'],array[1.0]) with ordinality as z(a,b,c,ord); select * from unnest(array[10,20],array['foo','bar'],array[1.0]) with ordinality as z(a,b,c,ord);
select * from table(unnest(array[10,20],array['foo','bar'],array[1.0])) with ordinality as z(a,b,c,ord); select * from rows from(unnest(array[10,20],array['foo','bar'],array[1.0])) with ordinality as z(a,b,c,ord);
select * from table(unnest(array[10,20],array['foo','bar']), generate_series(101,102)) with ordinality as z(a,b,c,ord); select * from rows from(unnest(array[10,20],array['foo','bar']), generate_series(101,102)) with ordinality as z(a,b,c,ord);
create temporary view vw_ord as select * from unnest(array[10,20],array['foo','bar'],array[1.0]) as z(a,b,c); create temporary view vw_ord as select * from unnest(array[10,20],array['foo','bar'],array[1.0]) as z(a,b,c);
select * from vw_ord; select * from vw_ord;
select definition from pg_views where viewname='vw_ord'; select definition from pg_views where viewname='vw_ord';
drop view vw_ord; drop view vw_ord;
create temporary view vw_ord as select * from table(unnest(array[10,20],array['foo','bar'],array[1.0])) as z(a,b,c); create temporary view vw_ord as select * from rows from(unnest(array[10,20],array['foo','bar'],array[1.0])) as z(a,b,c);
select * from vw_ord; select * from vw_ord;
select definition from pg_views where viewname='vw_ord'; select definition from pg_views where viewname='vw_ord';
drop view vw_ord; drop view vw_ord;
create temporary view vw_ord as select * from table(unnest(array[10,20],array['foo','bar']), generate_series(1,2)) as z(a,b,c); create temporary view vw_ord as select * from rows from(unnest(array[10,20],array['foo','bar']), generate_series(1,2)) as z(a,b,c);
select * from vw_ord; select * from vw_ord;
select definition from pg_views where viewname='vw_ord'; select definition from pg_views where viewname='vw_ord';
drop view vw_ord; drop view vw_ord;
-- ordinality and multiple functions vs. rewind and reverse scan -- ordinality and multiple functions vs. rewind and reverse scan
begin; begin;
declare foo scroll cursor for select * from table(generate_series(1,5),generate_series(1,2)) with ordinality as g(i,j,o); declare foo scroll cursor for select * from rows from(generate_series(1,5),generate_series(1,2)) with ordinality as g(i,j,o);
fetch all from foo; fetch all from foo;
fetch backward all from foo; fetch backward all from foo;
fetch all from foo; fetch all from foo;
...@@ -147,13 +147,13 @@ DROP VIEW vw_getfoo; ...@@ -147,13 +147,13 @@ DROP VIEW vw_getfoo;
-- sql, proretset = f, prorettype = record -- sql, proretset = f, prorettype = record
CREATE FUNCTION getfoo6(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; CREATE FUNCTION getfoo6(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo6(1) AS t1(fooid int, foosubid int, fooname text); SELECT * FROM getfoo6(1) AS t1(fooid int, foosubid int, fooname text);
SELECT * FROM TABLE( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY; SELECT * FROM ROWS FROM( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo6(1) AS CREATE VIEW vw_getfoo AS SELECT * FROM getfoo6(1) AS
(fooid int, foosubid int, fooname text); (fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo; SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo; DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS CREATE VIEW vw_getfoo AS
SELECT * FROM TABLE( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) SELECT * FROM ROWS FROM( getfoo6(1) AS (fooid int, foosubid int, fooname text) )
WITH ORDINALITY; WITH ORDINALITY;
SELECT * FROM vw_getfoo; SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo; DROP VIEW vw_getfoo;
...@@ -161,13 +161,13 @@ DROP VIEW vw_getfoo; ...@@ -161,13 +161,13 @@ DROP VIEW vw_getfoo;
-- sql, proretset = t, prorettype = record -- sql, proretset = t, prorettype = record
CREATE FUNCTION getfoo7(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; CREATE FUNCTION getfoo7(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo7(1) AS t1(fooid int, foosubid int, fooname text); SELECT * FROM getfoo7(1) AS t1(fooid int, foosubid int, fooname text);
SELECT * FROM TABLE( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY; SELECT * FROM ROWS FROM( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo7(1) AS CREATE VIEW vw_getfoo AS SELECT * FROM getfoo7(1) AS
(fooid int, foosubid int, fooname text); (fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo; SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo; DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS CREATE VIEW vw_getfoo AS
SELECT * FROM TABLE( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) SELECT * FROM ROWS FROM( getfoo7(1) AS (fooid int, foosubid int, fooname text) )
WITH ORDINALITY; WITH ORDINALITY;
SELECT * FROM vw_getfoo; SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo; DROP VIEW vw_getfoo;
...@@ -196,19 +196,19 @@ DROP VIEW vw_getfoo; ...@@ -196,19 +196,19 @@ DROP VIEW vw_getfoo;
-- mix 'n match kinds, to exercise expandRTE and related logic -- mix 'n match kinds, to exercise expandRTE and related logic
select * from table(getfoo1(1),getfoo2(1),getfoo3(1),getfoo4(1),getfoo5(1), select * from rows from(getfoo1(1),getfoo2(1),getfoo3(1),getfoo4(1),getfoo5(1),
getfoo6(1) AS (fooid int, foosubid int, fooname text), getfoo6(1) AS (fooid int, foosubid int, fooname text),
getfoo7(1) AS (fooid int, foosubid int, fooname text), getfoo7(1) AS (fooid int, foosubid int, fooname text),
getfoo8(1),getfoo9(1)) getfoo8(1),getfoo9(1))
with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u); with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u);
select * from table(getfoo9(1),getfoo8(1), select * from rows from(getfoo9(1),getfoo8(1),
getfoo7(1) AS (fooid int, foosubid int, fooname text), getfoo7(1) AS (fooid int, foosubid int, fooname text),
getfoo6(1) AS (fooid int, foosubid int, fooname text), getfoo6(1) AS (fooid int, foosubid int, fooname text),
getfoo5(1),getfoo4(1),getfoo3(1),getfoo2(1),getfoo1(1)) getfoo5(1),getfoo4(1),getfoo3(1),getfoo2(1),getfoo1(1))
with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u); with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u);
create temporary view vw_foo as create temporary view vw_foo as
select * from table(getfoo9(1), select * from rows from(getfoo9(1),
getfoo7(1) AS (fooid int, foosubid int, fooname text), getfoo7(1) AS (fooid int, foosubid int, fooname text),
getfoo1(1)) getfoo1(1))
with ordinality as t1(a,b,c,d,e,f,g,n); with ordinality as t1(a,b,c,d,e,f,g,n);
...@@ -252,7 +252,7 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) ON (r+i)<100; ...@@ -252,7 +252,7 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) ON (r+i)<100;
SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100; SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100;
SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN TABLE( foo_sql(11,13), foo_mat(11,13) ) WITH ORDINALITY AS f(i1,s1,i2,s2,o) ON (r+i1+i2)<100; SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN ROWS FROM( foo_sql(11,13), foo_mat(11,13) ) WITH ORDINALITY AS f(i1,s1,i2,s2,o) ON (r+i1+i2)<100;
SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) f(i) ON (r+i)<100; SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) f(i) ON (r+i)<100;
SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) WITH ORDINALITY AS f(i,o) ON (r+i)<100; SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) WITH ORDINALITY AS f(i,o) ON (r+i)<100;
...@@ -291,14 +291,14 @@ SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2) WITH ORD ...@@ -291,14 +291,14 @@ SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2) WITH ORD
-- selective rescan of multiple functions: -- selective rescan of multiple functions:
SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(11,11), foo_mat(10+r,13) ); SELECT * FROM (VALUES (1),(2),(3)) v(r), ROWS FROM( foo_sql(11,11), foo_mat(10+r,13) );
SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(10+r,13), foo_mat(11,11) ); SELECT * FROM (VALUES (1),(2),(3)) v(r), ROWS FROM( foo_sql(10+r,13), foo_mat(11,11) );
SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(10+r,13), foo_mat(10+r,13) ); SELECT * FROM (VALUES (1),(2),(3)) v(r), ROWS FROM( foo_sql(10+r,13), foo_mat(10+r,13) );
SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
SELECT * FROM generate_series(1,2) r1, generate_series(r1,3) r2, TABLE( foo_sql(10+r1,13), foo_mat(10+r2,13) ); SELECT * FROM generate_series(1,2) r1, generate_series(r1,3) r2, ROWS FROM( foo_sql(10+r1,13), foo_mat(10+r2,13) );
SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) f(i); SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) f(i);
SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) WITH ORDINALITY AS f(i,o); SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) WITH ORDINALITY AS f(i,o);
...@@ -550,12 +550,12 @@ SELECT * FROM get_users(); ...@@ -550,12 +550,12 @@ SELECT * FROM get_users();
SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes
-- multiple functions vs. dropped columns -- multiple functions vs. dropped columns
SELECT * FROM TABLE(generate_series(10,11), get_users()) WITH ORDINALITY; SELECT * FROM ROWS FROM(generate_series(10,11), get_users()) WITH ORDINALITY;
SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY; SELECT * FROM ROWS FROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
-- check that we can cope with post-parsing changes in rowtypes -- check that we can cope with post-parsing changes in rowtypes
create temp view usersview as create temp view usersview as
SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY; SELECT * FROM ROWS FROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
select * from usersview; select * from usersview;
alter table users drop column moredrop; alter table users drop column moredrop;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment