Skip to content

Commit b4af9e3

Browse files
committed
Ensure that pg_get_ruledef()'s output matches pg_get_viewdef()'s.
Various cases involving renaming of view columns are handled by having make_viewdef pass down the view's current relation tupledesc to get_query_def, which then takes care to use the column names from the tupledesc for the output column names of the SELECT. For some reason though, we'd missed teaching make_ruledef to do similarly when it is printing an ON SELECT rule, even though this is exactly the same case. The results from pg_get_ruledef would then be different and arguably wrong. In particular, this breaks pre-v10 versions of pg_dump, which in some situations would define views by means of emitting a CREATE RULE ... ON SELECT command. Third-party tools might not be happy either. In passing, clean up some crufty code in make_viewdef; we'd apparently modernized the equivalent code in make_ruledef somewhere along the way, and missed this copy. Per report from Gilles Darold. Back-patch to all supported versions. Discussion: https://postgr.es/m/ec05659a-40ff-4510-fc45-ca9d965d0838@dalibo.com
1 parent 278cb43 commit b4af9e3

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,6 +4590,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
45904590
char *ev_qual;
45914591
char *ev_action;
45924592
List *actions = NIL;
4593+
Relation ev_relation;
4594+
TupleDesc viewResultDesc = NULL;
45934595
int fno;
45944596
Datum dat;
45954597
bool isnull;
@@ -4626,6 +4628,8 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
46264628
if (ev_action != NULL)
46274629
actions = (List *) stringToNode(ev_action);
46284630

4631+
ev_relation = heap_open(ev_class, AccessShareLock);
4632+
46294633
/*
46304634
* Build the rules definition text
46314635
*/
@@ -4642,6 +4646,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
46424646
{
46434647
case '1':
46444648
appendStringInfoString(buf, "SELECT");
4649+
viewResultDesc = RelationGetDescr(ev_relation);
46454650
break;
46464651

46474652
case '2':
@@ -4731,7 +4736,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
47314736
foreach(action, actions)
47324737
{
47334738
query = (Query *) lfirst(action);
4734-
get_query_def(query, buf, NIL, NULL,
4739+
get_query_def(query, buf, NIL, viewResultDesc,
47354740
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
47364741
if (prettyFlags)
47374742
appendStringInfoString(buf, ";\n");
@@ -4749,10 +4754,12 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
47494754
Query *query;
47504755

47514756
query = (Query *) linitial(actions);
4752-
get_query_def(query, buf, NIL, NULL,
4757+
get_query_def(query, buf, NIL, viewResultDesc,
47534758
prettyFlags, WRAP_COLUMN_DEFAULT, 0);
47544759
appendStringInfoChar(buf, ';');
47554760
}
4761+
4762+
heap_close(ev_relation, AccessShareLock);
47564763
}
47574764

47584765

@@ -4774,20 +4781,28 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
47744781
List *actions = NIL;
47754782
Relation ev_relation;
47764783
int fno;
4784+
Datum dat;
47774785
bool isnull;
47784786

47794787
/*
47804788
* Get the attribute values from the rules tuple
47814789
*/
47824790
fno = SPI_fnumber(rulettc, "ev_type");
4783-
ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
4791+
dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4792+
Assert(!isnull);
4793+
ev_type = DatumGetChar(dat);
47844794

47854795
fno = SPI_fnumber(rulettc, "ev_class");
4786-
ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
4796+
dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4797+
Assert(!isnull);
4798+
ev_class = DatumGetObjectId(dat);
47874799

47884800
fno = SPI_fnumber(rulettc, "is_instead");
4789-
is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
4801+
dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
4802+
Assert(!isnull);
4803+
is_instead = DatumGetBool(dat);
47904804

4805+
/* these could be nulls */
47914806
fno = SPI_fnumber(rulettc, "ev_qual");
47924807
ev_qual = SPI_getvalue(ruletup, rulettc, fno);
47934808

src/test/regress/expected/create_view.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,35 @@ select pg_get_viewdef('tt22v', true);
16771677
LEFT JOIN tt6 ON TRUE;
16781678
(1 row)
16791679

1680+
-- check handling of views with immediately-renamed columns
1681+
create view tt23v (col_a, col_b) as
1682+
select q1 as other_name1, q2 as other_name2 from int8_tbl
1683+
union
1684+
select 42, 43;
1685+
select pg_get_viewdef('tt23v', true);
1686+
pg_get_viewdef
1687+
-------------------------------
1688+
SELECT int8_tbl.q1 AS col_a,+
1689+
int8_tbl.q2 AS col_b +
1690+
FROM int8_tbl +
1691+
UNION +
1692+
SELECT 42 AS col_a, +
1693+
43 AS col_b;
1694+
(1 row)
1695+
1696+
select pg_get_ruledef(oid, true) from pg_rewrite
1697+
where ev_class = 'tt23v'::regclass and ev_type = '1';
1698+
pg_get_ruledef
1699+
-----------------------------------------------------------------
1700+
CREATE RULE "_RETURN" AS +
1701+
ON SELECT TO tt23v DO INSTEAD SELECT int8_tbl.q1 AS col_a,+
1702+
int8_tbl.q2 AS col_b +
1703+
FROM int8_tbl +
1704+
UNION +
1705+
SELECT 42 AS col_a, +
1706+
43 AS col_b;
1707+
(1 row)
1708+
16801709
-- clean up all the random objects we made above
16811710
set client_min_messages = warning;
16821711
DROP SCHEMA temp_view_test CASCADE;

src/test/regress/sql/create_view.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,17 @@ create view tt22v as
569569
select * from tt5 natural left join tt6;
570570
select pg_get_viewdef('tt22v', true);
571571

572+
-- check handling of views with immediately-renamed columns
573+
574+
create view tt23v (col_a, col_b) as
575+
select q1 as other_name1, q2 as other_name2 from int8_tbl
576+
union
577+
select 42, 43;
578+
579+
select pg_get_viewdef('tt23v', true);
580+
select pg_get_ruledef(oid, true) from pg_rewrite
581+
where ev_class = 'tt23v'::regclass and ev_type = '1';
582+
572583
-- clean up all the random objects we made above
573584
set client_min_messages = warning;
574585
DROP SCHEMA temp_view_test CASCADE;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy