Skip to content

Commit e9f1c01

Browse files
committed
Fix dumping of views that are just VALUES(...) but have column aliases.
The "simple" path for printing VALUES clauses doesn't work if we need to attach nondefault column aliases, because there's noplace to do that in the minimal VALUES() syntax. So modify get_simple_values_rte() to detect nondefault aliases and treat that as a non-simple case. This further exposes that the "non-simple" path never actually worked; it didn't produce valid syntax. Fix that too. Per bug #12789 from Curtis McEnroe, and analysis by Andrew Gierth. Back-patch to all supported branches. Before 9.3, this also requires back-patching the part of commit 092d7de that created get_simple_values_rte() to begin with; inserting the extra test into the old factorization of that logic would've been too messy.
1 parent 8794bf1 commit e9f1c01

File tree

3 files changed

+107
-4
lines changed

3 files changed

+107
-4
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4498,10 +4498,7 @@ get_simple_values_rte(Query *query)
44984498
/*
44994499
* We want to return TRUE even if the Query also contains OLD or NEW rule
45004500
* RTEs. So the idea is to scan the rtable and see if there is only one
4501-
* inFromCl RTE that is a VALUES RTE. We don't look at the targetlist at
4502-
* all. This is okay because parser/analyze.c will never generate a
4503-
* "bare" VALUES RTE --- they only appear inside auto-generated
4504-
* sub-queries with very restricted structure.
4501+
* inFromCl RTE that is a VALUES RTE.
45054502
*/
45064503
foreach(lc, query->rtable)
45074504
{
@@ -4518,6 +4515,33 @@ get_simple_values_rte(Query *query)
45184515
else
45194516
return NULL; /* something else -> not simple VALUES */
45204517
}
4518+
4519+
/*
4520+
* We don't need to check the targetlist in any great detail, because
4521+
* parser/analyze.c will never generate a "bare" VALUES RTE --- they only
4522+
* appear inside auto-generated sub-queries with very restricted
4523+
* structure. However, DefineView might have modified the tlist by
4524+
* injecting new column aliases; so compare tlist resnames against the
4525+
* RTE's names to detect that.
4526+
*/
4527+
if (result)
4528+
{
4529+
ListCell *lcn;
4530+
4531+
if (list_length(query->targetList) != list_length(result->eref->colnames))
4532+
return NULL; /* this probably cannot happen */
4533+
forboth(lc, query->targetList, lcn, result->eref->colnames)
4534+
{
4535+
TargetEntry *tle = (TargetEntry *) lfirst(lc);
4536+
char *cname = strVal(lfirst(lcn));
4537+
4538+
if (tle->resjunk)
4539+
return NULL; /* this probably cannot happen */
4540+
if (tle->resname == NULL || strcmp(tle->resname, cname) != 0)
4541+
return NULL; /* column name has been changed */
4542+
}
4543+
}
4544+
45214545
return result;
45224546
}
45234547

@@ -8517,7 +8541,9 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
85178541
break;
85188542
case RTE_VALUES:
85198543
/* Values list RTE */
8544+
appendStringInfoChar(buf, '(');
85208545
get_values_def(rte->values_lists, context);
8546+
appendStringInfoChar(buf, ')');
85218547
break;
85228548
case RTE_CTE:
85238549
appendStringInfoString(buf, quote_identifier(rte->ctename));
@@ -8559,6 +8585,11 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
85598585
*/
85608586
printalias = true;
85618587
}
8588+
else if (rte->rtekind == RTE_VALUES)
8589+
{
8590+
/* Alias is syntactically required for VALUES */
8591+
printalias = true;
8592+
}
85628593
else if (rte->rtekind == RTE_CTE)
85638594
{
85648595
/*

src/test/regress/expected/rules.out

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,6 +2507,7 @@ select * from only t1_2;
25072507
19
25082508
(10 rows)
25092509

2510+
reset constraint_exclusion;
25102511
-- test various flavors of pg_get_viewdef()
25112512
select pg_get_viewdef('shoe'::regclass) as unpretty;
25122513
unpretty
@@ -2678,3 +2679,56 @@ ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renam
26782679
ERROR: renaming an ON SELECT rule is not allowed
26792680
DROP VIEW rule_v1;
26802681
DROP TABLE rule_t1;
2682+
--
2683+
-- check display of VALUES in view definitions
2684+
--
2685+
create view rule_v1 as values(1,2);
2686+
\d+ rule_v1
2687+
View "public.rule_v1"
2688+
Column | Type | Modifiers | Storage | Description
2689+
---------+---------+-----------+---------+-------------
2690+
column1 | integer | | plain |
2691+
column2 | integer | | plain |
2692+
View definition:
2693+
VALUES (1,2);
2694+
2695+
drop view rule_v1;
2696+
create view rule_v1(x) as values(1,2);
2697+
\d+ rule_v1
2698+
View "public.rule_v1"
2699+
Column | Type | Modifiers | Storage | Description
2700+
---------+---------+-----------+---------+-------------
2701+
x | integer | | plain |
2702+
column2 | integer | | plain |
2703+
View definition:
2704+
SELECT "*VALUES*".column1 AS x,
2705+
"*VALUES*".column2
2706+
FROM (VALUES (1,2)) "*VALUES*";
2707+
2708+
drop view rule_v1;
2709+
create view rule_v1(x) as select * from (values(1,2)) v;
2710+
\d+ rule_v1
2711+
View "public.rule_v1"
2712+
Column | Type | Modifiers | Storage | Description
2713+
---------+---------+-----------+---------+-------------
2714+
x | integer | | plain |
2715+
column2 | integer | | plain |
2716+
View definition:
2717+
SELECT v.column1 AS x,
2718+
v.column2
2719+
FROM ( VALUES (1,2)) v;
2720+
2721+
drop view rule_v1;
2722+
create view rule_v1(x) as select * from (values(1,2)) v(q,w);
2723+
\d+ rule_v1
2724+
View "public.rule_v1"
2725+
Column | Type | Modifiers | Storage | Description
2726+
--------+---------+-----------+---------+-------------
2727+
x | integer | | plain |
2728+
w | integer | | plain |
2729+
View definition:
2730+
SELECT v.q AS x,
2731+
v.w
2732+
FROM ( VALUES (1,2)) v(q, w);
2733+
2734+
drop view rule_v1;

src/test/regress/sql/rules.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,8 @@ select * from only t1;
953953
select * from only t1_1;
954954
select * from only t1_2;
955955

956+
reset constraint_exclusion;
957+
956958
-- test various flavors of pg_get_viewdef()
957959

958960
select pg_get_viewdef('shoe'::regclass) as unpretty;
@@ -1007,3 +1009,19 @@ ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renam
10071009

10081010
DROP VIEW rule_v1;
10091011
DROP TABLE rule_t1;
1012+
1013+
--
1014+
-- check display of VALUES in view definitions
1015+
--
1016+
create view rule_v1 as values(1,2);
1017+
\d+ rule_v1
1018+
drop view rule_v1;
1019+
create view rule_v1(x) as values(1,2);
1020+
\d+ rule_v1
1021+
drop view rule_v1;
1022+
create view rule_v1(x) as select * from (values(1,2)) v;
1023+
\d+ rule_v1
1024+
drop view rule_v1;
1025+
create view rule_v1(x) as select * from (values(1,2)) v(q,w);
1026+
\d+ rule_v1
1027+
drop view rule_v1;

0 commit comments

Comments
 (0)