Re: Alias of VALUES RTE in explain plan - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Alias of VALUES RTE in explain plan
Date
Msg-id 2192705.1730567369@sss.pgh.pa.us
Whole thread Raw
In response to Re: Alias of VALUES RTE in explain plan  (Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>)
Responses Re: Alias of VALUES RTE in explain plan
List pgsql-hackers
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> writes:
> On Tue, Oct 29, 2024 at 10:49 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> So what I now think
>> is that we ought to tweak the patch so that the parent alias is
>> pushed down only when the subquery contains just VALUES, no other
>> clauses.  Per a look at the grammar, ORDER BY, LIMIT, and FOR
>> UPDATE could conceivably appear alongside VALUES; although
>> FOR UPDATE would draw "FOR UPDATE cannot be applied to VALUES",
>> so maybe we needn't worry about it.

> If the user writes it in this manner, I think they intend to attach
> the alias to VALUES() since there's no other way to do it. What is
> weird is that they can use the alias before it's declared. For the
> sake of eliminating this weirdness, your proposed tweak sounds fine to
> me.

I was starting to come around to Andrei's position that changing this
behavior is fine, until I realized that it creates a problem for
ruleutils.c.  With the v2 patch, dumping a view that contains a
construct like this doesn't work:

regression=# create view vv as SELECT * FROM (VALUES (4),(2),(3),(1) ORDER BY t1.x LIMIT 2) AS t1(x);
      
CREATE VIEW
regression=# \d+ vv
                             View "public.vv"
 Column |  Type   | Collation | Nullable | Default | Storage | Description
--------+---------+-----------+----------+---------+---------+-------------
 x      | integer |           |          |         | plain   |
View definition:
 SELECT x
   FROM ( VALUES (4), (2), (3), (1)
          ORDER BY t1_1.x
         LIMIT 2) t1(x);

ruleutils has decided that it needs to make the two "t1" table
aliases distinct.  But of course that will fail on reload:

regression=# SELECT x
regression-#    FROM ( VALUES (4), (2), (3), (1)
regression(#           ORDER BY t1_1.x
regression(#          LIMIT 2) t1(x);
ERROR:  missing FROM-clause entry for table "t1_1"
LINE 3:           ORDER BY t1_1.x
                           ^

Now maybe we could teach ruleutils that these table aliases don't have
to be distinct.  But that feels fragile, and it's work that we'd be
expending only so that we can break any existing SQL code that's
using this construct.  That's enough to put me firmly on the side of
"let's not change that behavior".

It seems sufficient to avoid alias pushdown when there's an ORDER BY
inside the VALUES subquery.  We disallow a locking clause, and
while there can be LIMIT/OFFSET, those aren't allowed to reference the
VALUES output anyway.  I added some test cases to show that this is
enough to make view-dumping behave sanely.

            regards, tom lane

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index f2bcd6aa98..73dd1d80c8 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -8992,16 +8992,16 @@ insert into utrtest values (2, 'qux');
 -- with a non-direct modification plan
 explain (verbose, costs off)
 update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
-                                           QUERY PLAN
-------------------------------------------------------------------------------------------------
+                                        QUERY PLAN
+-------------------------------------------------------------------------------------------
  Update on public.utrtest
-   Output: utrtest_1.a, utrtest_1.b, "*VALUES*".column1
+   Output: utrtest_1.a, utrtest_1.b, s.x
    Foreign Update on public.remp utrtest_1
      Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 RETURNING a, b
    Update on public.locp utrtest_2
    ->  Hash Join
-         Output: 1, "*VALUES*".*, "*VALUES*".column1, utrtest.tableoid, utrtest.ctid, utrtest.*
-         Hash Cond: (utrtest.a = "*VALUES*".column1)
+         Output: 1, s.*, s.x, utrtest.tableoid, utrtest.ctid, utrtest.*
+         Hash Cond: (utrtest.a = s.x)
          ->  Append
                ->  Foreign Scan on public.remp utrtest_1
                      Output: utrtest_1.a, utrtest_1.tableoid, utrtest_1.ctid, utrtest_1.*
@@ -9009,9 +9009,9 @@ update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
                ->  Seq Scan on public.locp utrtest_2
                      Output: utrtest_2.a, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
          ->  Hash
-               Output: "*VALUES*".*, "*VALUES*".column1
-               ->  Values Scan on "*VALUES*"
-                     Output: "*VALUES*".*, "*VALUES*".column1
+               Output: s.*, s.x
+               ->  Values Scan on s
+                     Output: s.*, s.x
 (18 rows)

 update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
@@ -9049,16 +9049,16 @@ ERROR:  cannot route tuples into foreign table to be updated "remp"
 -- with a non-direct modification plan
 explain (verbose, costs off)
 update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *;
-                                             QUERY PLAN
------------------------------------------------------------------------------------------------------
+                                        QUERY PLAN
+-------------------------------------------------------------------------------------------
  Update on public.utrtest
-   Output: utrtest_1.a, utrtest_1.b, "*VALUES*".column1
+   Output: utrtest_1.a, utrtest_1.b, s.x
    Update on public.locp utrtest_1
    Foreign Update on public.remp utrtest_2
      Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 RETURNING a, b
    ->  Hash Join
-         Output: 3, "*VALUES*".*, "*VALUES*".column1, utrtest.tableoid, utrtest.ctid, (NULL::record)
-         Hash Cond: (utrtest.a = "*VALUES*".column1)
+         Output: 3, s.*, s.x, utrtest.tableoid, utrtest.ctid, (NULL::record)
+         Hash Cond: (utrtest.a = s.x)
          ->  Append
                ->  Seq Scan on public.locp utrtest_1
                      Output: utrtest_1.a, utrtest_1.tableoid, utrtest_1.ctid, NULL::record
@@ -9066,9 +9066,9 @@ update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *;
                      Output: utrtest_2.a, utrtest_2.tableoid, utrtest_2.ctid, utrtest_2.*
                      Remote SQL: SELECT a, b, ctid FROM public.loct FOR UPDATE
          ->  Hash
-               Output: "*VALUES*".*, "*VALUES*".column1
-               ->  Values Scan on "*VALUES*"
-                     Output: "*VALUES*".*, "*VALUES*".column1
+               Output: s.*, s.x
+               ->  Values Scan on s
+                     Output: s.*, s.x
 (18 rows)

 update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR
diff --git a/contrib/tsm_system_rows/expected/tsm_system_rows.out
b/contrib/tsm_system_rows/expected/tsm_system_rows.out
index 87b4a8fc64..cd472d2605 100644
--- a/contrib/tsm_system_rows/expected/tsm_system_rows.out
+++ b/contrib/tsm_system_rows/expected/tsm_system_rows.out
@@ -49,13 +49,13 @@ SELECT * FROM
   (VALUES (0),(10),(100)) v(nrows),
   LATERAL (SELECT count(*) FROM test_tablesample
            TABLESAMPLE system_rows (nrows)) ss;
-                        QUERY PLAN
-----------------------------------------------------------
+                  QUERY PLAN
+-----------------------------------------------
  Nested Loop
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
    ->  Aggregate
          ->  Sample Scan on test_tablesample
-               Sampling: system_rows ("*VALUES*".column1)
+               Sampling: system_rows (v.nrows)
 (5 rows)

 SELECT * FROM
diff --git a/contrib/tsm_system_time/expected/tsm_system_time.out
b/contrib/tsm_system_time/expected/tsm_system_time.out
index ac44f30be9..6c5aac3709 100644
--- a/contrib/tsm_system_time/expected/tsm_system_time.out
+++ b/contrib/tsm_system_time/expected/tsm_system_time.out
@@ -47,7 +47,7 @@ SELECT * FROM
          ->  Materialize
                ->  Sample Scan on test_tablesample
                      Sampling: system_time ('100000'::double precision)
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
 (6 rows)

 SELECT * FROM
@@ -65,14 +65,14 @@ SELECT * FROM
   (VALUES (0),(100000)) v(time),
   LATERAL (SELECT COUNT(*) FROM test_tablesample
            TABLESAMPLE system_time (time)) ss;
-                           QUERY PLAN
-----------------------------------------------------------------
+                      QUERY PLAN
+------------------------------------------------------
  Nested Loop
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
    ->  Aggregate
          ->  Materialize
                ->  Sample Scan on test_tablesample
-                     Sampling: system_time ("*VALUES*".column1)
+                     Sampling: system_time (v."time")
 (6 rows)

 SELECT * FROM
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 506e063161..fb8f433a2a 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -221,6 +221,7 @@ parse_analyze_withcb(RawStmt *parseTree, const char *sourceText,
 Query *
 parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
                   CommonTableExpr *parentCTE,
+                  Alias *parentAlias,
                   bool locked_from_parent,
                   bool resolve_unknowns)
 {
@@ -228,6 +229,7 @@ parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
     Query       *query;

     pstate->p_parent_cte = parentCTE;
+    pstate->p_parent_alias = parentAlias;
     pstate->p_locked_from_parent = locked_from_parent;
     pstate->p_resolve_unknowns = resolve_unknowns;

@@ -1578,6 +1580,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
     List      **colexprs = NULL;
     int            sublist_length = -1;
     bool        lateral = false;
+    Alias       *valias;
     ParseNamespaceItem *nsitem;
     ListCell   *lc;
     ListCell   *lc2;
@@ -1725,11 +1728,20 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
         lateral = true;

     /*
-     * Generate the VALUES RTE
+     * Generate the VALUES RTE.  If we're in a RangeSubselect of an outer
+     * query level, and that had an Alias, we prefer to use that alias rather
+     * than "*VALUES*".columnN.  But stick with "*VALUES*" if there is a
+     * sortClause, because that could contain references to the "*VALUES*"
+     * names.  (If we supported a lockingClause, that could too; but we
+     * don't.)
      */
+    if (pstate->p_parent_alias && stmt->sortClause == NIL)
+        valias = copyObject(pstate->p_parent_alias);
+    else
+        valias = NULL;
     nsitem = addRangeTableEntryForValues(pstate, exprsLists,
                                          coltypes, coltypmods, colcollations,
-                                         NULL, lateral, true);
+                                         valias, lateral, true);
     addNSItemToQuery(pstate, nsitem, true, true, true);

     /*
@@ -2167,7 +2179,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
          * namespace list.
          */
         selectQuery = parse_sub_analyze((Node *) stmt, pstate,
-                                        NULL, false, false);
+                                        NULL, NULL, false, false);

         /*
          * Check for bogus references to Vars on the current query level (but
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 979926b605..5040b64274 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -428,6 +428,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
      * might still be required (if there is an all-tables locking clause).
      */
     query = parse_sub_analyze(r->subquery, pstate, NULL,
+                              r->alias,
                               isLockedRefname(pstate,
                                               r->alias == NULL ? NULL :
                                               r->alias->aliasname),
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index de9ae9b483..9070f834b5 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -312,7 +312,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
     }

     /* Now we can get on with analyzing the CTE's query */
-    query = parse_sub_analyze(cte->ctequery, pstate, cte, false, true);
+    query = parse_sub_analyze(cte->ctequery, pstate, cte, NULL, false, true);
     cte->ctequery = (Node *) query;

     /*
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index c2806297aa..8e8aff0c35 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -1878,7 +1878,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
     /*
      * OK, let's transform the sub-SELECT.
      */
-    qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true);
+    qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, NULL,
+                              false, true);

     /*
      * Check that we got a SELECT.  Anything else should be impossible given
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
index 28b66fccb4..f63c6ed25f 100644
--- a/src/include/parser/analyze.h
+++ b/src/include/parser/analyze.h
@@ -36,6 +36,7 @@ extern Query *parse_analyze_withcb(RawStmt *parseTree, const char *sourceText,

 extern Query *parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
                                 CommonTableExpr *parentCTE,
+                                Alias *parentAlias,
                                 bool locked_from_parent,
                                 bool resolve_unknowns);

diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 2375e95c10..87aec73827 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -161,6 +161,9 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
  * p_parent_cte: CommonTableExpr that immediately contains the current query,
  * if any.
  *
+ * p_parent_alias: Alias attached to the current sub-SELECT in the parent
+ * query level, if any.
+ *
  * p_target_relation: target relation, if query is INSERT/UPDATE/DELETE/MERGE
  *
  * p_target_nsitem: target relation's ParseNamespaceItem.
@@ -222,6 +225,7 @@ struct ParseState
     List       *p_ctenamespace; /* current namespace for common table exprs */
     List       *p_future_ctes;    /* common table exprs not yet in namespace */
     CommonTableExpr *p_parent_cte;    /* this query's containing CTE */
+    Alias       *p_parent_alias; /* outer level's alias for this query */
     Relation    p_target_relation;    /* INSERT/UPDATE/DELETE/MERGE target rel */
     ParseNamespaceItem *p_target_nsitem;    /* target rel's NSItem, or NULL */
     ParseNamespaceItem *p_grouping_nsitem;    /* NSItem for grouping, or NULL */
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index f551624afb..5c18230b27 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -2189,34 +2189,34 @@ select pg_get_viewdef('tt25v', true);
 -- also check cases seen only in EXPLAIN
 explain (verbose, costs off)
 select * from tt24v;
-                                        QUERY PLAN
-------------------------------------------------------------------------------------------
+                                QUERY PLAN
+--------------------------------------------------------------------------
  Hash Join
-   Output: (cte.r).column2, ((ROW("*VALUES*".column1, "*VALUES*".column2))).column2
-   Hash Cond: ((cte.r).column1 = ((ROW("*VALUES*".column1, "*VALUES*".column2))).column1)
+   Output: (cte.r).column2, ((ROW(rr.column1, rr.column2))).column2
+   Hash Cond: ((cte.r).column1 = ((ROW(rr.column1, rr.column2))).column1)
    CTE cte
-     ->  Values Scan on "*VALUES*_1"
-           Output: ROW("*VALUES*_1".column1, "*VALUES*_1".column2)
+     ->  Values Scan on r
+           Output: ROW(r.column1, r.column2)
    ->  CTE Scan on cte
          Output: cte.r
    ->  Hash
-         Output: (ROW("*VALUES*".column1, "*VALUES*".column2))
+         Output: (ROW(rr.column1, rr.column2))
          ->  Limit
-               Output: (ROW("*VALUES*".column1, "*VALUES*".column2))
-               ->  Values Scan on "*VALUES*"
-                     Output: ROW("*VALUES*".column1, "*VALUES*".column2)
+               Output: (ROW(rr.column1, rr.column2))
+               ->  Values Scan on rr
+                     Output: ROW(rr.column1, rr.column2)
 (14 rows)

 explain (verbose, costs off)
 select (r).column2 from (select r from (values(1,2),(3,4)) r limit 1) ss;
-                            QUERY PLAN
--------------------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  Subquery Scan on ss
    Output: (ss.r).column2
    ->  Limit
-         Output: (ROW("*VALUES*".column1, "*VALUES*".column2))
-         ->  Values Scan on "*VALUES*"
-               Output: ROW("*VALUES*".column1, "*VALUES*".column2)
+         Output: (ROW(r.column1, r.column2))
+         ->  Values Scan on r
+               Output: ROW(r.column1, r.column2)
 (6 rows)

 -- test pretty-print parenthesization rules, and SubLink deparsing
@@ -2265,6 +2265,67 @@ select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system
 (1 row)

 reset restrict_nonsystem_relation_kind;
+-- test assignment of aliases to VALUES clauses
+create view tt28v as
+select *
+from (values (4),(2),(3),(1) order by "*VALUES*".column1 limit 2) as t1(x);
+select pg_get_viewdef('tt28v', true);
+            pg_get_viewdef
+---------------------------------------
+  SELECT x                            +
+    FROM ( VALUES (4), (2), (3), (1)  +
+           ORDER BY "*VALUES*".column1+
+          LIMIT 2) t1(x);
+(1 row)
+
+explain (verbose, costs off) select * from tt28v where x > 0;
+                   QUERY PLAN
+------------------------------------------------
+ Subquery Scan on t1
+   Output: t1.x
+   Filter: (t1.x > 0)
+   ->  Limit
+         Output: "*VALUES*".column1
+         ->  Sort
+               Output: "*VALUES*".column1
+               Sort Key: "*VALUES*".column1
+               ->  Values Scan on "*VALUES*"
+                     Output: "*VALUES*".column1
+(10 rows)
+
+create view tt29v as
+select *
+from (values (4),(2),(3),(1) order by "*VALUES*".column1) t1(a),
+     (values (9),(8),(6),(7) order by "*VALUES*".column1) t2(b);
+select pg_get_viewdef('tt29v', true);
+                pg_get_viewdef
+-----------------------------------------------
+  SELECT t1.a,                                +
+     t2.b                                     +
+    FROM ( VALUES (4), (2), (3), (1)          +
+           ORDER BY "*VALUES*".column1) t1(a),+
+     ( VALUES (9), (8), (6), (7)              +
+           ORDER BY "*VALUES*".column1) t2(b);
+(1 row)
+
+explain (verbose, costs off) select * from tt29v where a > 0;
+                     QUERY PLAN
+----------------------------------------------------
+ Nested Loop
+   Output: "*VALUES*".column1, "*VALUES*_1".column1
+   ->  Sort
+         Output: "*VALUES*".column1
+         Sort Key: "*VALUES*".column1
+         ->  Values Scan on "*VALUES*"
+               Output: "*VALUES*".column1
+               Filter: ("*VALUES*".column1 > 0)
+   ->  Sort
+         Output: "*VALUES*_1".column1
+         Sort Key: "*VALUES*_1".column1
+         ->  Values Scan on "*VALUES*_1"
+               Output: "*VALUES*_1".column1
+(13 rows)
+
 -- clean up all the random objects we made above
 DROP SCHEMA temp_view_test CASCADE;
 NOTICE:  drop cascades to 27 other objects
@@ -2296,7 +2357,7 @@ drop cascades to view aliased_view_2
 drop cascades to view aliased_view_3
 drop cascades to view aliased_view_4
 DROP SCHEMA testviewschm2 CASCADE;
-NOTICE:  drop cascades to 80 other objects
+NOTICE:  drop cascades to 82 other objects
 DETAIL:  drop cascades to table t1
 drop cascades to view temporal1
 drop cascades to view temporal2
@@ -2377,3 +2438,5 @@ drop cascades to view tt25v
 drop cascades to view tt26v
 drop cascades to table tt27v_tbl
 drop cascades to view tt27v
+drop cascades to view tt28v
+drop cascades to view tt29v
diff --git a/src/test/regress/expected/gist.out b/src/test/regress/expected/gist.out
index c75bbb23b6..af85945ea4 100644
--- a/src/test/regress/expected/gist.out
+++ b/src/test/regress/expected/gist.out
@@ -141,11 +141,11 @@ cross join lateral
                              QUERY PLAN
 --------------------------------------------------------------------
  Nested Loop
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
    ->  Limit
          ->  Index Only Scan using gist_tbl_point_index on gist_tbl
-               Index Cond: (p <@ "*VALUES*".column1)
-               Order By: (p <-> ("*VALUES*".column1)[0])
+               Index Cond: (p <@ v.bb)
+               Order By: (p <-> (v.bb)[0])
 (6 rows)

 select p from
diff --git a/src/test/regress/expected/groupingsets.out b/src/test/regress/expected/groupingsets.out
index d7c9b44605..bed1174c13 100644
--- a/src/test/regress/expected/groupingsets.out
+++ b/src/test/regress/expected/groupingsets.out
@@ -846,17 +846,17 @@ select v.c, (select count(*) from gstest2 group by () having v.c)
 explain (costs off)
   select v.c, (select count(*) from gstest2 group by () having v.c)
     from (values (false),(true)) v(c) order by v.c;
-                        QUERY PLAN
------------------------------------------------------------
+                  QUERY PLAN
+-----------------------------------------------
  Sort
-   Sort Key: "*VALUES*".column1
-   ->  Values Scan on "*VALUES*"
+   Sort Key: v.c
+   ->  Values Scan on v
          SubPlan 1
            ->  Aggregate
                  Group Key: ()
-                 Filter: "*VALUES*".column1
+                 Filter: v.c
                  ->  Result
-                       One-Time Filter: "*VALUES*".column1
+                       One-Time Filter: v.c
                        ->  Seq Scan on gstest2
 (10 rows)

@@ -1349,15 +1349,15 @@ explain (costs off)
     from (values (1),(2)) v(x), gstest_data(v.x)
    group by grouping sets (a,b)
    order by 3, 1, 2;
-                             QUERY PLAN
----------------------------------------------------------------------
+                      QUERY PLAN
+------------------------------------------------------
  Sort
-   Sort Key: (sum("*VALUES*".column1)), gstest_data.a, gstest_data.b
+   Sort Key: (sum(v.x)), gstest_data.a, gstest_data.b
    ->  HashAggregate
          Hash Key: gstest_data.a
          Hash Key: gstest_data.b
          ->  Nested Loop
-               ->  Values Scan on "*VALUES*"
+               ->  Values Scan on v
                ->  Function Scan on gstest_data
 (8 rows)

@@ -1481,7 +1481,7 @@ explain (costs off)
          Hash Key: gstest_data.b
          Group Key: ()
          ->  Nested Loop
-               ->  Values Scan on "*VALUES*"
+               ->  Values Scan on v
                ->  Function Scan on gstest_data
 (10 rows)

@@ -2323,16 +2323,16 @@ select distinct on (a, b) a, b
 from (values (1, 1), (2, 2)) as t (a, b) where a = b
 group by grouping sets((a, b), (a))
 order by a, b;
-                           QUERY PLAN
-----------------------------------------------------------------
+             QUERY PLAN
+-------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1, "*VALUES*".column2
+         Sort Key: t.a, t.b
          ->  HashAggregate
-               Hash Key: "*VALUES*".column1, "*VALUES*".column2
-               Hash Key: "*VALUES*".column1
-               ->  Values Scan on "*VALUES*"
-                     Filter: (column1 = column2)
+               Hash Key: t.a, t.b
+               Hash Key: t.a
+               ->  Values Scan on t
+                     Filter: (a = b)
 (8 rows)

 select distinct on (a, b) a, b
@@ -2352,16 +2352,16 @@ select distinct on (a, b+1) a, b+1
 from (values (1, 0), (2, 1)) as t (a, b) where a = b+1
 group by grouping sets((a, b+1), (a))
 order by a, b+1;
-                              QUERY PLAN
-----------------------------------------------------------------------
+                QUERY PLAN
+-------------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1, (("*VALUES*".column2 + 1))
+         Sort Key: t.a, ((t.b + 1))
          ->  HashAggregate
-               Hash Key: "*VALUES*".column1, ("*VALUES*".column2 + 1)
-               Hash Key: "*VALUES*".column1
-               ->  Values Scan on "*VALUES*"
-                     Filter: (column1 = (column2 + 1))
+               Hash Key: t.a, (t.b + 1)
+               Hash Key: t.a
+               ->  Values Scan on t
+                     Filter: (a = (b + 1))
 (8 rows)

 select distinct on (a, b+1) a, b+1
@@ -2381,15 +2381,15 @@ select a, b
 from (values (1, 1), (2, 2)) as t (a, b) where a = b
 group by grouping sets((a, b), (a))
 order by a, b nulls first;
-                           QUERY PLAN
-----------------------------------------------------------------
+            QUERY PLAN
+----------------------------------
  Sort
-   Sort Key: "*VALUES*".column1, "*VALUES*".column2 NULLS FIRST
+   Sort Key: t.a, t.b NULLS FIRST
    ->  HashAggregate
-         Hash Key: "*VALUES*".column1, "*VALUES*".column2
-         Hash Key: "*VALUES*".column1
-         ->  Values Scan on "*VALUES*"
-               Filter: (column1 = column2)
+         Hash Key: t.a, t.b
+         Hash Key: t.a
+         ->  Values Scan on t
+               Filter: (a = b)
 (7 rows)

 select a, b
@@ -2427,16 +2427,16 @@ explain (costs off)
 select a, b, row_number() over (order by a, b nulls first)
 from (values (1, 1), (2, 2)) as t (a, b) where a = b
 group by grouping sets((a, b), (a));
-                              QUERY PLAN
-----------------------------------------------------------------------
+               QUERY PLAN
+----------------------------------------
  WindowAgg
    ->  Sort
-         Sort Key: "*VALUES*".column1, "*VALUES*".column2 NULLS FIRST
+         Sort Key: t.a, t.b NULLS FIRST
          ->  HashAggregate
-               Hash Key: "*VALUES*".column1, "*VALUES*".column2
-               Hash Key: "*VALUES*".column1
-               ->  Values Scan on "*VALUES*"
-                     Filter: (column1 = column2)
+               Hash Key: t.a, t.b
+               Hash Key: t.a
+               ->  Values Scan on t
+                     Filter: (a = b)
 (8 rows)

 select a, b, row_number() over (order by a, b nulls first)
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 9b2973694f..3bd75074ba 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -4508,16 +4508,16 @@ select * from
 (values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys)
 left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x
 left join unnest(v1ys) as u1(u1y) on u1y = v2y;
-                         QUERY PLAN
--------------------------------------------------------------
+               QUERY PLAN
+----------------------------------------
  Nested Loop Left Join
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v1
    ->  Hash Right Join
-         Hash Cond: (u1.u1y = "*VALUES*_1".column2)
-         Filter: ("*VALUES*_1".column1 = "*VALUES*".column1)
+         Hash Cond: (u1.u1y = v2.v2y)
+         Filter: (v2.v2x = v1.v1x)
          ->  Function Scan on unnest u1
          ->  Hash
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on v2
 (8 rows)

 select * from
@@ -4654,10 +4654,10 @@ using (join_key);
                                 QUERY PLAN
 --------------------------------------------------------------------------
  Nested Loop Left Join
-   Output: "*VALUES*".column1, i1.f1, (666)
-   Join Filter: ("*VALUES*".column1 = i1.f1)
-   ->  Values Scan on "*VALUES*"
-         Output: "*VALUES*".column1
+   Output: foo1.join_key, i1.f1, (666)
+   Join Filter: (foo1.join_key = i1.f1)
+   ->  Values Scan on foo1
+         Output: foo1.join_key
    ->  Materialize
          Output: i1.f1, (666)
          ->  Nested Loop Left Join
@@ -6541,12 +6541,12 @@ explain (costs off)
    ->  Nested Loop
          ->  Nested Loop
                ->  Index Only Scan using tenk1_unique1 on tenk1 a
-               ->  Values Scan on "*VALUES*"
+               ->  Values Scan on ss
          ->  Memoize
-               Cache Key: "*VALUES*".column1
+               Cache Key: ss.x
                Cache Mode: logical
                ->  Index Only Scan using tenk1_unique2 on tenk1 b
-                     Index Cond: (unique2 = "*VALUES*".column1)
+                     Index Cond: (unique2 = ss.x)
 (10 rows)

 select count(*) from tenk1 a,
@@ -7326,12 +7326,12 @@ select * from
   lateral (select f1 from int4_tbl
            where f1 = any (select unique1 from tenk1
                            where unique2 = v.x offset 0)) ss;
-                              QUERY PLAN
-----------------------------------------------------------------------
+                            QUERY PLAN
+------------------------------------------------------------------
  Nested Loop
-   Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1
-   ->  Values Scan on "*VALUES*"
-         Output: "*VALUES*".column1, "*VALUES*".column2
+   Output: v.id, v.x, int4_tbl.f1
+   ->  Values Scan on v
+         Output: v.id, v.x
    ->  Nested Loop Semi Join
          Output: int4_tbl.f1
          Join Filter: (int4_tbl.f1 = tenk1.unique1)
@@ -7341,7 +7341,7 @@ select * from
                Output: tenk1.unique1
                ->  Index Scan using tenk1_unique2 on public.tenk1
                      Output: tenk1.unique1
-                     Index Cond: (tenk1.unique2 = "*VALUES*".column2)
+                     Index Cond: (tenk1.unique2 = v.x)
 (14 rows)

 select * from
@@ -7368,13 +7368,13 @@ lateral (select * from int8_tbl t1,
                                                          QUERY PLAN
     

----------------------------------------------------------------------------------------------------------------------------
  Nested Loop
-   Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2
+   Output: v.id, t1.q1, t1.q2, ss2.q1, ss2.q2
    ->  Seq Scan on public.int8_tbl t1
          Output: t1.q1, t1.q2
    ->  Nested Loop
-         Output: "*VALUES*".column1, ss2.q1, ss2.q2
-         ->  Values Scan on "*VALUES*"
-               Output: "*VALUES*".column1
+         Output: v.id, ss2.q1, ss2.q2
+         ->  Values Scan on v
+               Output: v.id
          ->  Subquery Scan on ss2
                Output: ss2.q1, ss2.q2
                Filter: (t1.q1 = ss2.q2)
@@ -7390,7 +7390,7 @@ lateral (select * from int8_tbl t1,
                                      Output: GREATEST(t1.q1, t2.q2)
                              InitPlan 2
                                ->  Result
-                                     Output: ("*VALUES*".column1 = 0)
+                                     Output: (v.id = 0)
                              ->  Seq Scan on public.int8_tbl t3
                                    Output: t3.q1, t3.q2
                                    Filter: (t3.q2 = (InitPlan 1).col1)
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 0a6945581b..ac0bafe21f 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -5180,10 +5180,10 @@ select consumes_rw_array(a), a from returns_rw_array(1) a;
 explain (verbose, costs off)
 select consumes_rw_array(a), a from
   (values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
-                             QUERY PLAN
----------------------------------------------------------------------
- Values Scan on "*VALUES*"
-   Output: consumes_rw_array("*VALUES*".column1), "*VALUES*".column1
+              QUERY PLAN
+---------------------------------------
+ Values Scan on v
+   Output: consumes_rw_array(v.a), v.a
 (2 rows)

 select consumes_rw_array(a), a from
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 9168979a62..efe8bf1ef6 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -1193,10 +1193,10 @@ explain (verbose, costs off)
 select r, r is null as isnull, r is not null as isnotnull
 from (values (1,row(1,2)), (1,row(null,null)), (1,null),
              (null,row(1,2)), (null,row(null,null)), (null,null) ) r(a,b);
-                                                                                                         QUERY PLAN
                                                                                                      

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- Values Scan on "*VALUES*"
-   Output: ROW("*VALUES*".column1, "*VALUES*".column2), (("*VALUES*".column1 IS NULL) AND ("*VALUES*".column2 IS NOT
DISTINCTFROM NULL)), (("*VALUES*".column1 IS NOT NULL) AND ("*VALUES*".column2 IS DISTINCT FROM NULL)) 
+                                                            QUERY PLAN
            

+-----------------------------------------------------------------------------------------------------------------------------------
+ Values Scan on r
+   Output: ROW(r.a, r.b), ((r.a IS NULL) AND (r.b IS NOT DISTINCT FROM NULL)), ((r.a IS NOT NULL) AND (r.b IS DISTINCT
FROMNULL)) 
 (2 rows)

 select r, r is null as isnull, r is not null as isnotnull
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index d17ade278b..84c70efda3 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -432,7 +432,7 @@ select * from
                                 QUERY PLAN
 --------------------------------------------------------------------------
  Nested Loop Left Join
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
    ->  Finalize Aggregate
          ->  Gather
                Workers Planned: 4
@@ -458,7 +458,7 @@ select * from
                                       QUERY PLAN
 --------------------------------------------------------------------------------------
  Nested Loop Left Join
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
    ->  Finalize Aggregate
          ->  Gather
                Workers Planned: 4
@@ -609,7 +609,7 @@ select * from explain_parallel_sort_stats();
                        explain_parallel_sort_stats
 --------------------------------------------------------------------------
  Nested Loop Left Join (actual rows=30000 loops=1)
-   ->  Values Scan on "*VALUES*" (actual rows=3 loops=1)
+   ->  Values Scan on v (actual rows=3 loops=1)
    ->  Gather Merge (actual rows=10000 loops=3)
          Workers Planned: 4
          Workers Launched: 4
@@ -873,7 +873,7 @@ select * from
                         QUERY PLAN
 ----------------------------------------------------------
  Nested Loop Left Join
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
    ->  Finalize GroupAggregate
          Group Key: tenk1.string4
          ->  Gather Merge
diff --git a/src/test/regress/expected/sqljson.out b/src/test/regress/expected/sqljson.out
index 435d61dd4a..90959fe79b 100644
--- a/src/test/regress/expected/sqljson.out
+++ b/src/test/regress/expected/sqljson.out
@@ -1070,15 +1070,15 @@ DROP VIEW json_arrayagg_view;
 -- Test JSON_ARRAY(subquery) deparsing
 EXPLAIN (VERBOSE, COSTS OFF)
 SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING jsonb);
-                             QUERY PLAN
----------------------------------------------------------------------
+                       QUERY PLAN
+--------------------------------------------------------
  Result
    Output: (InitPlan 1).col1
    InitPlan 1
      ->  Aggregate
-           Output: JSON_ARRAYAGG("*VALUES*".column1 RETURNING jsonb)
-           ->  Values Scan on "*VALUES*"
-                 Output: "*VALUES*".column1
+           Output: JSON_ARRAYAGG(foo.i RETURNING jsonb)
+           ->  Values Scan on foo
+                 Output: foo.i
 (7 rows)

 CREATE VIEW json_array_subquery_view AS
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 2d35de3fad..95cc0545ae 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -1124,7 +1124,7 @@ explain (verbose, costs off)
     (select (select now()) as x from (values(1),(2)) v(y)) ss;
                    QUERY PLAN
 ------------------------------------------------
- Values Scan on "*VALUES*"
+ Values Scan on v
    Output: (InitPlan 1).col1, (InitPlan 2).col1
    InitPlan 1
      ->  Result
@@ -1141,7 +1141,7 @@ explain (verbose, costs off)
 -----------------------------------
  Subquery Scan on ss
    Output: ss.x, ss.x
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
          Output: (InitPlan 1).col1
          InitPlan 1
            ->  Result
@@ -1151,33 +1151,33 @@ explain (verbose, costs off)
 explain (verbose, costs off)
   select x, x from
     (select (select now() where y=y) as x from (values(1),(2)) v(y)) ss;
-                              QUERY PLAN
-----------------------------------------------------------------------
- Values Scan on "*VALUES*"
+               QUERY PLAN
+----------------------------------------
+ Values Scan on v
    Output: (SubPlan 1), (SubPlan 2)
    SubPlan 1
      ->  Result
            Output: now()
-           One-Time Filter: ("*VALUES*".column1 = "*VALUES*".column1)
+           One-Time Filter: (v.y = v.y)
    SubPlan 2
      ->  Result
            Output: now()
-           One-Time Filter: ("*VALUES*".column1 = "*VALUES*".column1)
+           One-Time Filter: (v.y = v.y)
 (10 rows)

 explain (verbose, costs off)
   select x, x from
     (select (select random() where y=y) as x from (values(1),(2)) v(y)) ss;
-                                 QUERY PLAN
-----------------------------------------------------------------------------
+                  QUERY PLAN
+----------------------------------------------
  Subquery Scan on ss
    Output: ss.x, ss.x
-   ->  Values Scan on "*VALUES*"
+   ->  Values Scan on v
          Output: (SubPlan 1)
          SubPlan 1
            ->  Result
                  Output: random()
-                 One-Time Filter: ("*VALUES*".column1 = "*VALUES*".column1)
+                 One-Time Filter: (v.y = v.y)
 (8 rows)

 --
@@ -1366,13 +1366,13 @@ select * from
   (3 not in (select * from (values (1), (2)) ss1)),
   (false)
 ) ss;
-               QUERY PLAN
-----------------------------------------
- Values Scan on "*VALUES*"
-   Output: "*VALUES*".column1
+          QUERY PLAN
+-------------------------------
+ Values Scan on ss
+   Output: ss.column1
    SubPlan 1
-     ->  Values Scan on "*VALUES*_1"
-           Output: "*VALUES*_1".column1
+     ->  Values Scan on ss1
+           Output: ss1.column1
 (5 rows)

 select * from
diff --git a/src/test/regress/expected/tablesample.out b/src/test/regress/expected/tablesample.out
index 9ff4611640..34b39a7153 100644
--- a/src/test/regress/expected/tablesample.out
+++ b/src/test/regress/expected/tablesample.out
@@ -251,14 +251,14 @@ select pct, count(unique1) from
   (values (0),(100)) v(pct),
   lateral (select * from tenk1 tablesample bernoulli (pct)) ss
   group by pct;
-                       QUERY PLAN
---------------------------------------------------------
+                QUERY PLAN
+-------------------------------------------
  HashAggregate
-   Group Key: "*VALUES*".column1
+   Group Key: v.pct
    ->  Nested Loop
-         ->  Values Scan on "*VALUES*"
+         ->  Values Scan on v
          ->  Sample Scan on tenk1
-               Sampling: bernoulli ("*VALUES*".column1)
+               Sampling: bernoulli (v.pct)
 (6 rows)

 select pct, count(unique1) from
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index c73631a9a1..19cb0cb7d5 100644
--- a/src/test/regress/expected/union.out
+++ b/src/test/regress/expected/union.out
@@ -481,27 +481,27 @@ reset enable_hashagg;
 set enable_hashagg to on;
 explain (costs off)
 select x from (values ('11'::varbit), ('10'::varbit)) _(x) union select x from (values ('11'::varbit), ('10'::varbit))
_(x);
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 set enable_hashagg to off;
 explain (costs off)
 select x from (values ('11'::varbit), ('10'::varbit)) _(x) union select x from (values ('11'::varbit), ('10'::varbit))
_(x);
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 reset enable_hashagg;
@@ -509,13 +509,13 @@ reset enable_hashagg;
 set enable_hashagg to on;
 explain (costs off)
 select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4]))
_(x);
-               QUERY PLAN
------------------------------------------
+           QUERY PLAN
+--------------------------------
  HashAggregate
-   Group Key: "*VALUES*".column1
+   Group Key: _.x
    ->  Append
-         ->  Values Scan on "*VALUES*"
-         ->  Values Scan on "*VALUES*_1"
+         ->  Values Scan on _
+         ->  Values Scan on __1
 (5 rows)

 select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4]))
_(x);
@@ -528,14 +528,14 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (va

 explain (costs off)
 select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4]))
_(x);
-                  QUERY PLAN
------------------------------------------------
+                QUERY PLAN
+-------------------------------------------
  HashSetOp Intersect
    ->  Append
          ->  Subquery Scan on "*SELECT* 1"
-               ->  Values Scan on "*VALUES*"
+               ->  Values Scan on _
          ->  Subquery Scan on "*SELECT* 2"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4]))
_(x);
@@ -546,14 +546,14 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from

 explain (costs off)
 select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4]))
_(x);
-                  QUERY PLAN
------------------------------------------------
+                QUERY PLAN
+-------------------------------------------
  HashSetOp Except
    ->  Append
          ->  Subquery Scan on "*SELECT* 1"
-               ->  Values Scan on "*VALUES*"
+               ->  Values Scan on _
          ->  Subquery Scan on "*SELECT* 2"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4]))
_(x);
@@ -565,14 +565,14 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (v
 -- non-hashable type
 explain (costs off)
 select x from (values (array['10'::varbit]), (array['11'::varbit])) _(x) union select x from (values
(array['10'::varbit]),(array['01'::varbit])) _(x); 
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (array['10'::varbit]), (array['11'::varbit])) _(x) union select x from (values
(array['10'::varbit]),(array['01'::varbit])) _(x); 
@@ -586,14 +586,14 @@ select x from (values (array['10'::varbit]), (array['11'::varbit])) _(x) union s
 set enable_hashagg to off;
 explain (costs off)
 select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4]))
_(x);
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (values (array[1, 2]), (array[1, 4]))
_(x);
@@ -606,16 +606,16 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (va

 explain (costs off)
 select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4]))
_(x);
-                     QUERY PLAN
------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  SetOp Intersect
    ->  Sort
          Sort Key: "*SELECT* 1".x
          ->  Append
                ->  Subquery Scan on "*SELECT* 1"
-                     ->  Values Scan on "*VALUES*"
+                     ->  Values Scan on _
                ->  Subquery Scan on "*SELECT* 2"
-                     ->  Values Scan on "*VALUES*_1"
+                     ->  Values Scan on __1
 (8 rows)

 select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4]))
_(x);
@@ -626,16 +626,16 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from

 explain (costs off)
 select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4]))
_(x);
-                     QUERY PLAN
------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  SetOp Except
    ->  Sort
          Sort Key: "*SELECT* 1".x
          ->  Append
                ->  Subquery Scan on "*SELECT* 1"
-                     ->  Values Scan on "*VALUES*"
+                     ->  Values Scan on _
                ->  Subquery Scan on "*SELECT* 2"
-                     ->  Values Scan on "*VALUES*_1"
+                     ->  Values Scan on __1
 (8 rows)

 select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4]))
_(x);
@@ -649,14 +649,14 @@ reset enable_hashagg;
 set enable_hashagg to on;
 explain (costs off)
 select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
@@ -669,16 +669,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values

 explain (costs off)
 select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
-                     QUERY PLAN
------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  SetOp Intersect
    ->  Sort
          Sort Key: "*SELECT* 1".x
          ->  Append
                ->  Subquery Scan on "*SELECT* 1"
-                     ->  Values Scan on "*VALUES*"
+                     ->  Values Scan on _
                ->  Subquery Scan on "*SELECT* 2"
-                     ->  Values Scan on "*VALUES*_1"
+                     ->  Values Scan on __1
 (8 rows)

 select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
@@ -689,16 +689,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (va

 explain (costs off)
 select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
-                     QUERY PLAN
------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  SetOp Except
    ->  Sort
          Sort Key: "*SELECT* 1".x
          ->  Append
                ->  Subquery Scan on "*SELECT* 1"
-                     ->  Values Scan on "*VALUES*"
+                     ->  Values Scan on _
                ->  Subquery Scan on "*SELECT* 2"
-                     ->  Values Scan on "*VALUES*_1"
+                     ->  Values Scan on __1
 (8 rows)

 select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
@@ -712,14 +712,14 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (value
 -- type is hashable.  (Otherwise, this would fail at execution time.)
 explain (costs off)
 select x from (values (row('10'::varbit)), (row('11'::varbit))) _(x) union select x from (values (row('10'::varbit)),
(row('01'::varbit)))_(x); 
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (row('10'::varbit)), (row('11'::varbit))) _(x) union select x from (values (row('10'::varbit)),
(row('01'::varbit)))_(x); 
@@ -735,14 +735,14 @@ select x from (values (row('10'::varbit)), (row('11'::varbit))) _(x) union selec
 create type ct1 as (f1 varbit);
 explain (costs off)
 select x from (values (row('10'::varbit)::ct1), (row('11'::varbit)::ct1)) _(x) union select x from (values
(row('10'::varbit)::ct1),(row('01'::varbit)::ct1)) _(x); 
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (row('10'::varbit)::ct1), (row('11'::varbit)::ct1)) _(x) union select x from (values
(row('10'::varbit)::ct1),(row('01'::varbit)::ct1)) _(x); 
@@ -757,14 +757,14 @@ drop type ct1;
 set enable_hashagg to off;
 explain (costs off)
 select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
-                  QUERY PLAN
------------------------------------------------
+              QUERY PLAN
+--------------------------------------
  Unique
    ->  Sort
-         Sort Key: "*VALUES*".column1
+         Sort Key: _.x
          ->  Append
-               ->  Values Scan on "*VALUES*"
-               ->  Values Scan on "*VALUES*_1"
+               ->  Values Scan on _
+               ->  Values Scan on __1
 (6 rows)

 select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);
@@ -777,16 +777,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values

 explain (costs off)
 select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
-                     QUERY PLAN
------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  SetOp Intersect
    ->  Sort
          Sort Key: "*SELECT* 1".x
          ->  Append
                ->  Subquery Scan on "*SELECT* 1"
-                     ->  Values Scan on "*VALUES*"
+                     ->  Values Scan on _
                ->  Subquery Scan on "*SELECT* 2"
-                     ->  Values Scan on "*VALUES*_1"
+                     ->  Values Scan on __1
 (8 rows)

 select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x);
@@ -797,16 +797,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (va

 explain (costs off)
 select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
-                     QUERY PLAN
------------------------------------------------------
+                   QUERY PLAN
+-------------------------------------------------
  SetOp Except
    ->  Sort
          Sort Key: "*SELECT* 1".x
          ->  Append
                ->  Subquery Scan on "*SELECT* 1"
-                     ->  Values Scan on "*VALUES*"
+                     ->  Values Scan on _
                ->  Subquery Scan on "*SELECT* 2"
-                     ->  Values Scan on "*VALUES*_1"
+                     ->  Values Scan on __1
 (8 rows)

 select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out
index 8786058ed0..7ce7cddb5b 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -2988,15 +2988,15 @@ EXPLAIN (costs off)
 MERGE INTO rw_view1 t
   USING (VALUES ('Tom'), ('Dick'), ('Harry')) AS v(person) ON t.person = v.person
   WHEN MATCHED AND snoop(t.person) THEN UPDATE SET person = v.person;
-                         QUERY PLAN
--------------------------------------------------------------
+                     QUERY PLAN
+-----------------------------------------------------
  Merge on base_tbl
    ->  Nested Loop
-         Join Filter: (base_tbl.person = "*VALUES*".column1)
+         Join Filter: (base_tbl.person = v.person)
          ->  Seq Scan on base_tbl
                Filter: (visibility = 'public'::text)
          ->  Materialize
-               ->  Values Scan on "*VALUES*"
+               ->  Values Scan on v
 (7 rows)

 -- security barrier view on top of security barrier view
@@ -3090,10 +3090,10 @@ MERGE INTO rw_view2 t
 -------------------------------------------------------------------------
  Merge on base_tbl
    ->  Nested Loop
-         Join Filter: (base_tbl.person = "*VALUES*".column1)
+         Join Filter: (base_tbl.person = v.person)
          ->  Seq Scan on base_tbl
                Filter: ((visibility = 'public'::text) AND snoop(person))
-         ->  Values Scan on "*VALUES*"
+         ->  Values Scan on v
 (6 rows)

 DROP TABLE base_tbl CASCADE;
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index ae6841308b..39983481a0 100644
--- a/src/test/regress/sql/create_view.sql
+++ b/src/test/regress/sql/create_view.sql
@@ -838,6 +838,21 @@ insert into tt27v values (1); -- Error
 select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view.
 reset restrict_nonsystem_relation_kind;

+-- test assignment of aliases to VALUES clauses
+
+create view tt28v as
+select *
+from (values (4),(2),(3),(1) order by "*VALUES*".column1 limit 2) as t1(x);
+select pg_get_viewdef('tt28v', true);
+explain (verbose, costs off) select * from tt28v where x > 0;
+
+create view tt29v as
+select *
+from (values (4),(2),(3),(1) order by "*VALUES*".column1) t1(a),
+     (values (9),(8),(6),(7) order by "*VALUES*".column1) t2(b);
+select pg_get_viewdef('tt29v', true);
+explain (verbose, costs off) select * from tt29v where a > 0;
+
 -- clean up all the random objects we made above
 DROP SCHEMA temp_view_test CASCADE;
 DROP SCHEMA testviewschm2 CASCADE;

pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: What is a typical precision of gettimeofday()?
Next
From: "bigbro_wq@hotmail.com"
Date:
Subject: Repeat the condition check twice in function distribute_qual_to_rels