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().
This commit is contained in:
Noah Misch 2013-12-10 09:34:37 -05:00
parent 01cc1fecfd
commit 53685d7981
11 changed files with 123 additions and 123 deletions

View File

@ -647,7 +647,7 @@ FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow'))
</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
result rows in this case is that of the largest function result, with
smaller results padded with NULLs to match.
@ -655,7 +655,7 @@ FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow'))
<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>
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>
<para>
@ -674,7 +674,7 @@ TABLE( <replaceable>function_call</replaceable> <optional>, ... </optional> ) <o
any number of array parameters, and it returns a corresponding number of
columns, as if <literal>UNNEST</literal>
(<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>
<synopsis>
@ -683,7 +683,7 @@ UNNEST( <replaceable>array_expression</replaceable> <optional>, ... </optional>
<para>
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.
</para>
@ -731,20 +731,20 @@ SELECT * FROM vw_getfoo;
<synopsis>
<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>)
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>
<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
alias list that could otherwise be attached to the <literal>FROM</>
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
each member function separately; or if there is only one member function
and no <literal>WITH ORDINALITY</> clause,
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>

View File

@ -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> [, ...] ) ] ]
[ 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 ] 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> [, ...] ) ] ]
<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> [ * ]
<para>
Multiple function calls can be combined into a
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
row from each function, etc. If some of the functions produce fewer
rows than others, NULLs are substituted for the missing data, so
@ -410,18 +410,18 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
</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
the column definition list after the function call inside
<literal>TABLE( ... )</>. A column definition list can be placed
after the <literal>TABLE( ... )</> construct only if there's just a
single function and no <literal>WITH ORDINALITY</> clause.
<literal>ROWS FROM( ... )</>. A column definition list can be placed
after the <literal>ROWS FROM( ... )</> construct only if there's just
a single function and no <literal>WITH ORDINALITY</> clause.
</para>
<para>
To use <literal>ORDINALITY</literal> together with a column definition
list, you must use the <literal>TABLE( ... )</> syntax and put the
column definition list inside <literal>TABLE( ... )</>.
list, you must use the <literal>ROWS FROM( ... )</> syntax and put the
column definition list inside <literal>ROWS FROM( ... )</>.
</para>
</listitem>
</varlistentry>
@ -1811,8 +1811,7 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
</para>
<para>
Placing multiple function calls inside <literal>TABLE( ... )</> syntax is
also an extension of the SQL standard.
<literal>ROWS FROM( ... )</> is an extension of the SQL standard.
</para>
</refsect2>

View File

@ -2310,7 +2310,7 @@ _copyRangeFunction(const RangeFunction *from)
COPY_SCALAR_FIELD(lateral);
COPY_SCALAR_FIELD(ordinality);
COPY_SCALAR_FIELD(is_table);
COPY_SCALAR_FIELD(is_rowsfrom);
COPY_NODE_FIELD(functions);
COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(coldeflist);

View File

@ -2142,7 +2142,7 @@ _equalRangeFunction(const RangeFunction *a, const RangeFunction *b)
{
COMPARE_SCALAR_FIELD(lateral);
COMPARE_SCALAR_FIELD(ordinality);
COMPARE_SCALAR_FIELD(is_table);
COMPARE_SCALAR_FIELD(is_rowsfrom);
COMPARE_NODE_FIELD(functions);
COMPARE_NODE_FIELD(alias);
COMPARE_NODE_FIELD(coldeflist);

View File

@ -2629,7 +2629,7 @@ _outRangeFunction(StringInfo str, const RangeFunction *node)
WRITE_BOOL_FIELD(lateral);
WRITE_BOOL_FIELD(ordinality);
WRITE_BOOL_FIELD(is_table);
WRITE_BOOL_FIELD(is_rowsfrom);
WRITE_NODE_FIELD(functions);
WRITE_NODE_FIELD(alias);
WRITE_NODE_FIELD(coldeflist);

View File

@ -406,7 +406,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
a_expr b_expr c_expr AexprConst indirection_el
columnref in_expr having_clause func_table array_expr
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 <list> ExclusionConstraintList ExclusionConstraintElem
%type <list> func_arg_list
@ -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
* a plain function call, like "foo(...)", or a TABLE expression with
* one or more function calls, "TABLE (foo(...), bar(...))",
* a plain function call, like "foo(...)", or a ROWS FROM expression with
* one or more function calls, "ROWS FROM (foo(...), bar(...))",
* 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:
* TABLE (foo() AS (foo_res_a text, foo_res_b text),
* bar() AS (bar_res_a text, bar_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))
* 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.
*/
@ -9995,29 +9995,30 @@ func_table: func_expr_windowless opt_ordinality
RangeFunction *n = makeNode(RangeFunction);
n->lateral = false;
n->ordinality = $2;
n->is_table = false;
n->is_rowsfrom = false;
n->functions = list_make1(list_make2($1, NIL));
/* alias and coldeflist are set by table_ref production */
$$ = (Node *) n;
}
| TABLE '(' func_table_list ')' opt_ordinality
| ROWS FROM '(' rowsfrom_list ')' opt_ordinality
{
RangeFunction *n = makeNode(RangeFunction);
n->lateral = false;
n->ordinality = $5;
n->is_table = true;
n->functions = $3;
n->ordinality = $6;
n->is_rowsfrom = true;
n->functions = $4;
/* alias and coldeflist are set by table_ref production */
$$ = (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); }
;
func_table_list: func_table_item { $$ = list_make1($1); }
| func_table_list ',' func_table_item { $$ = lappend($1, $3); }
rowsfrom_list:
rowsfrom_item { $$ = list_make1($1); }
| rowsfrom_list ',' rowsfrom_item { $$ = lappend($1, $3); }
;
opt_col_def_list: AS '(' TableFuncElementList ')' { $$ = $3; }

View File

@ -655,25 +655,25 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
* expansion) and no WITH ORDINALITY. The reason for the latter
* 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
* in one direction or the other. Putting the coldeflist inside TABLE()
* is much clearer in this case.
* in one direction or the other. Putting the coldeflist inside ROWS
* FROM() is much clearer in this case.
*/
if (r->coldeflist)
{
if (list_length(funcexprs) != 1)
{
if (r->is_table)
if (r->is_rowsfrom)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("TABLE() with multiple functions cannot have a column definition list"),
errhint("Put a separate column definition list for each function inside TABLE()."),
errmsg("ROWS FROM() with multiple functions cannot have a column definition list"),
errhint("Put a separate column definition list for each function inside ROWS FROM()."),
parser_errposition(pstate,
exprLocation((Node *) r->coldeflist))));
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
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,
exprLocation((Node *) r->coldeflist))));
}
@ -681,7 +681,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
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,
exprLocation((Node *) r->coldeflist))));

View File

@ -8125,10 +8125,10 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
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,
* we must use TABLE() syntax to avoid ambiguity about whether
* the coldeflist includes the ordinality column.
* we must use ROWS FROM() syntax to avoid ambiguity about
* whether the coldeflist includes the ordinality column.
*/
if (list_length(rte->functions) == 1 &&
(rtfunc1->funccolnames == NIL || !rte->funcordinality))
@ -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-
* future-proof assumptions about what the parser would do
* with the output; but the alternative is to emit our
* nonstandard extended TABLE() notation for what might
* have been a perfectly spec-compliant multi-argument
* nonstandard ROWS FROM() notation for what might have
* been a perfectly spec-compliant multi-argument
* UNNEST().
*/
all_unnest = true;
@ -8189,7 +8189,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
{
int funcno = 0;
appendStringInfoString(buf, "TABLE(");
appendStringInfoString(buf, "ROWS FROM(");
foreach(lc, rte->functions)
{
RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
@ -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
* 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.
* Pass NULL for colinfo to select the latter behavior.
*

View File

@ -466,11 +466,11 @@ typedef struct RangeSubselect
* RangeFunction - function call appearing in a FROM clause
*
* 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
* call tree, and the second element being a possibly-empty list of ColumnDef
* 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
* at the top level. (We disallow coldeflist appearing both here and
@ -481,7 +481,7 @@ typedef struct RangeFunction
NodeTag type;
bool lateral; /* does it have LATERAL prefix? */
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 */
Alias *alias; /* table alias & optional column aliases */
List *coldeflist; /* list of ColumnDef nodes to describe result

View File

@ -97,14 +97,14 @@ select definition from pg_views where viewname='vw_ord';
drop view vw_ord;
-- 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);
a | b | c | d | ord
---+-----+---+----+-----
1 | 11 | 2 | 22 | 1
1 | 111 | | | 2
(2 rows)
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;
n | a | b | c | d | ord
---+---+----+---+----+-----
@ -112,16 +112,16 @@ select * from vw_ord;
(1 row)
select definition from pg_views where viewname='vw_ord';
definition
-----------------------------------------------------------------------------------------
SELECT v.n, +
z.a, +
z.b, +
z.c, +
z.d, +
z.ord +
FROM (( VALUES (1)) v(n) +
JOIN TABLE(foot(1), foot(2)) WITH ORDINALITY z(a, b, c, d, ord) ON ((v.n = z.ord)));
definition
---------------------------------------------------------------------------------------------
SELECT v.n, +
z.a, +
z.b, +
z.c, +
z.d, +
z.ord +
FROM (( VALUES (1)) v(n) +
JOIN ROWS FROM(foot(1), foot(2)) WITH ORDINALITY z(a, b, c, d, ord) ON ((v.n = z.ord)));
(1 row)
drop view vw_ord;
@ -140,14 +140,14 @@ select * from unnest(array[10,20],array['foo','bar'],array[1.0]) with ordinality
20 | bar | | 2
(2 rows)
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);
a | b | c | ord
----+-----+-----+-----
10 | foo | 1.0 | 1
20 | bar | | 2
(2 rows)
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);
a | b | c | ord
----+-----+-----+-----
10 | foo | 101 | 1
@ -172,7 +172,7 @@ select definition from pg_views where viewname='vw_ord';
(1 row)
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;
a | b | c
----+-----+-----
@ -190,7 +190,7 @@ select definition from pg_views where viewname='vw_ord';
(1 row)
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;
a | b | c
----+-----+---
@ -199,18 +199,18 @@ select * from vw_ord;
(2 rows)
select definition from pg_views where viewname='vw_ord';
definition
------------------------------------------------------------------------------------------------------------------
SELECT z.a, +
z.b, +
z.c +
FROM TABLE(unnest(ARRAY[10, 20]), unnest(ARRAY['foo'::text, 'bar'::text]), generate_series(1, 2)) z(a, b, c);
definition
----------------------------------------------------------------------------------------------------------------------
SELECT z.a, +
z.b, +
z.c +
FROM ROWS FROM(unnest(ARRAY[10, 20]), unnest(ARRAY['foo'::text, 'bar'::text]), generate_series(1, 2)) z(a, b, c);
(1 row)
drop view vw_ord;
-- ordinality and multiple functions vs. rewind and reverse scan
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;
i | j | o
---+---+---
@ -525,7 +525,7 @@ SELECT * FROM getfoo6(1) AS t1(fooid int, foosubid int, fooname text);
1 | 1 | Joe
(1 row)
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;
fooid | foosubid | fooname | ordinality
-------+----------+---------+------------
1 | 1 | Joe | 1
@ -541,7 +541,7 @@ SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
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;
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname | ordinality
@ -559,7 +559,7 @@ SELECT * FROM getfoo7(1) AS t1(fooid int, foosubid int, fooname text);
1 | 2 | Ed
(2 rows)
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;
fooid | foosubid | fooname | ordinality
-------+----------+---------+------------
1 | 1 | Joe | 1
@ -577,7 +577,7 @@ SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
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;
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname | ordinality
@ -648,7 +648,7 @@ SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
-- 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),
getfoo7(1) AS (fooid int, foosubid int, fooname text),
getfoo8(1),getfoo9(1))
@ -659,7 +659,7 @@ select * from table(getfoo1(1),getfoo2(1),getfoo3(1),getfoo4(1),getfoo5(1),
| 1 | Ed | | | | 1 | 2 | Ed | | | | 1 | 2 | Ed | | | | | 2
(2 rows)
select * from table(getfoo9(1),getfoo8(1),
select * from rows from(getfoo9(1),getfoo8(1),
getfoo7(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))
@ -671,7 +671,7 @@ select * from table(getfoo9(1),getfoo8(1),
(2 rows)
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),
getfoo1(1))
with ordinality as t1(a,b,c,d,e,f,g,n);
@ -683,17 +683,17 @@ select * from vw_foo;
(2 rows)
select pg_get_viewdef('vw_foo');
pg_get_viewdef
--------------------------------------------------------------------------------------------------------------------------------------------------
SELECT t1.a, +
t1.b, +
t1.c, +
t1.d, +
t1.e, +
t1.f, +
t1.g, +
t1.n +
FROM TABLE(getfoo9(1), getfoo7(1) AS (fooid integer, foosubid integer, fooname text), getfoo1(1)) WITH ORDINALITY t1(a, b, c, d, e, f, g, n);
pg_get_viewdef
------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT t1.a, +
t1.b, +
t1.c, +
t1.d, +
t1.e, +
t1.f, +
t1.g, +
t1.n +
FROM ROWS FROM(getfoo9(1), getfoo7(1) AS (fooid integer, foosubid integer, fooname text), getfoo1(1)) WITH ORDINALITY t1(a, b, c, d, e, f, g, n);
(1 row)
drop view vw_foo;
@ -805,7 +805,7 @@ SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
1 | 1
(1 row)
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;
r | i1 | s1 | i2 | s2 | o
---+----+----+----+----+---
1 | 11 | 1 | 11 | 1 | 1
@ -1103,7 +1103,7 @@ SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
1 | 1
(1 row)
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) );
r | i | s | i | s
---+----+---+----+---
1 | 11 | 1 | 11 | 1
@ -1120,7 +1120,7 @@ SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
1 | 1
(1 row)
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) );
r | i | s | i | s
---+----+---+----+---
1 | 11 | 1 | 11 | 1
@ -1137,7 +1137,7 @@ SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
1 | 1
(1 row)
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) );
r | i | s | i | s
---+----+---+----+---
1 | 11 | 1 | 11 | 1
@ -1154,7 +1154,7 @@ SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false);
1 | 1
(1 row)
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) );
r1 | r2 | i | s | i | s
----+----+----+----+----+---
1 | 1 | 11 | 1 | 11 | 1
@ -1905,14 +1905,14 @@ SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes
(2 rows)
-- 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;
generate_series | userid | seq | email | moredrop | enabled | ordinality
-----------------+--------+-----+--------+----------+---------+------------
10 | id | 1 | email | 11 | t | 1
11 | id2 | 2 | email2 | 12 | t | 2
(2 rows)
SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY;
SELECT * FROM ROWS FROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
userid | seq | email | moredrop | enabled | generate_series | ordinality
--------+-----+--------+----------+---------+-----------------+------------
id | 1 | email | 11 | t | 10 | 1
@ -1921,7 +1921,7 @@ SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY;
-- check that we can cope with post-parsing changes in rowtypes
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;
userid | seq | email | moredrop | enabled | generate_series | ordinality
--------+-----+--------+----------+---------+-----------------+------------

View File

@ -24,8 +24,8 @@ select definition from pg_views where viewname='vw_ord';
drop view vw_ord;
-- multiple functions
select * from table(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);
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 rows from(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord) on (n=ord);
select * from vw_ord;
select definition from pg_views where viewname='vw_ord';
drop view vw_ord;
@ -33,24 +33,24 @@ drop view vw_ord;
-- 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]) 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 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'],array[1.0])) 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);
select * from vw_ord;
select definition from pg_views where viewname='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 definition from pg_views where viewname='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 definition from pg_views where viewname='vw_ord';
drop view vw_ord;
-- ordinality and multiple functions vs. rewind and reverse scan
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 backward all from foo;
fetch all from foo;
@ -147,13 +147,13 @@ DROP VIEW vw_getfoo;
-- sql, proretset = f, prorettype = record
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 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
(fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
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;
SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
@ -161,13 +161,13 @@ DROP VIEW vw_getfoo;
-- sql, proretset = t, prorettype = record
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 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
(fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
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;
SELECT * FROM vw_getfoo;
DROP VIEW vw_getfoo;
@ -196,19 +196,19 @@ DROP VIEW vw_getfoo;
-- 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),
getfoo7(1) AS (fooid int, foosubid int, fooname text),
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);
select * from table(getfoo9(1),getfoo8(1),
select * from rows from(getfoo9(1),getfoo8(1),
getfoo7(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))
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
select * from table(getfoo9(1),
select * from rows from(getfoo9(1),
getfoo7(1) AS (fooid int, foosubid int, fooname text),
getfoo1(1))
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;
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 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) 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
-- selective rescan of multiple functions:
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 * 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 * 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 * 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) WITH ORDINALITY AS f(i,o);
@ -550,12 +550,12 @@ SELECT * FROM get_users();
SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes
-- multiple functions vs. dropped columns
SELECT * FROM TABLE(generate_series(10,11), get_users()) WITH ORDINALITY;
SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY;
SELECT * FROM ROWS FROM(generate_series(10,11), get_users()) 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
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;
alter table users drop column moredrop;