From 53685d79813a46c7e3a46ae4b1210f608d41d6ab Mon Sep 17 00:00:00 2001
From: Noah Misch <noah@leadboat.com>
Date: Tue, 10 Dec 2013 09:34:37 -0500
Subject: [PATCH] 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().
---
 doc/src/sgml/queries.sgml                | 16 ++--
 doc/src/sgml/ref/select.sgml             | 19 +++--
 src/backend/nodes/copyfuncs.c            |  2 +-
 src/backend/nodes/equalfuncs.c           |  2 +-
 src/backend/nodes/outfuncs.c             |  2 +-
 src/backend/parser/gram.y                | 29 +++----
 src/backend/parser/parse_clause.c        | 14 ++--
 src/backend/utils/adt/ruleutils.c        | 14 ++--
 src/include/nodes/parsenodes.h           |  6 +-
 src/test/regress/expected/rangefuncs.out | 98 ++++++++++++------------
 src/test/regress/sql/rangefuncs.sql      | 44 +++++------
 11 files changed, 123 insertions(+), 123 deletions(-)

diff --git a/doc/src/sgml/queries.sgml b/doc/src/sgml/queries.sgml
index b33de682005..daba74bd631 100644
--- a/doc/src/sgml/queries.sgml
+++ b/doc/src/sgml/queries.sgml
@@ -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>
diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml
index 88ebd73d49c..d6a17cc7a44 100644
--- a/doc/src/sgml/ref/select.sgml
+++ b/doc/src/sgml/ref/select.sgml
@@ -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>
 
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index e3edcf6f74f..cd8a11b8d5d 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -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);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 1f9b5d70f55..6188114060f 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -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);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4c7505e3341..22c7d40156b 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -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);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 19220971da6..8fced4427b1 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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; }
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 8b4c0ae0d3b..939fa834e0a 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -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))));
 
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 348f620f2a4..86c0a582539 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -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.
  *
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 6a5555f918d..0ad7586853b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -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
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 418f92c4dbe..a988dd01a12 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -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 
 --------+-----+--------+----------+---------+-----------------+------------
diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql
index 7ba8cbb3042..ac2769fdba9 100644
--- a/src/test/regress/sql/rangefuncs.sql
+++ b/src/test/regress/sql/rangefuncs.sql
@@ -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;
-- 
GitLab