From: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
---|---|
To: | Robert Haas <robertmhaas(at)gmail(dot)com> |
Cc: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: Making view dump/restore safe at the column-alias level |
Date: | 2012-12-22 02:46:17 |
Message-ID: | 15151.1356144377@sss.pgh.pa.us |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Robert Haas <robertmhaas(at)gmail(dot)com> writes:
> I'm having a hard time following this. Can you provide a concrete example?
regression=# create table t1 (x int, y int);
CREATE TABLE
regression=# create table t2 (x int, z int);
CREATE TABLE
regression=# create view v1 as select * from t1 join t2 using (x);
CREATE VIEW
regression=# \d+ v1
View "public.v1"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+---------+-------------
x | integer | | plain |
y | integer | | plain |
z | integer | | plain |
View definition:
SELECT t1.x, t1.y, t2.z
FROM t1
JOIN t2 USING (x);
regression=# alter table t2 rename column x to q;
ALTER TABLE
regression=# \d+ v1
View "public.v1"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+---------+-------------
x | integer | | plain |
y | integer | | plain |
z | integer | | plain |
View definition:
SELECT t1.x, t1.y, t2.z
FROM t1
JOIN t2 USING (x);
At this point the dumped view definition is wrong: if you try to execute
it you get
regression=# SELECT t1.x, t1.y, t2.z
regression-# FROM t1
regression-# JOIN t2 USING (x);
ERROR: column "x" specified in USING clause does not exist in right table
I'm suggesting that we could fix this by emitting something that forces
the right alias to be assigned to t2.q:
SELECT t1.x, t1.y, t2.z
FROM t1
JOIN t2 AS t2(x,z)
USING (x);
The implementation I have in mind is to recurse down the join tree and
have any JOIN USING item forcibly propagate the common column name as
the alias-to-use for each of the two input columns.
Also consider
regression=# create view v2 as select * from (select 1,2) as a(x,y)
regression-# union select * from (select 3,4) as b;
CREATE VIEW
regression=# \d+ v2
View "public.v2"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+---------+-------------
x | integer | | plain |
y | integer | | plain |
View definition:
SELECT a.x, a.y
FROM ( SELECT 1, 2) a(x, y)
UNION
SELECT b."?column?" AS x, b."?column?" AS y
FROM ( SELECT 3, 4) b;
That view definition doesn't work either, as complained of today in
pgsql-general. To fix this we just need to force the columns of b
to be given distinct aliases. The minimum-new-code solution would
probably be to produce
SELECT a.x, a.y
FROM ( SELECT 1, 2) a(x, y)
UNION
SELECT b."?column?" AS x, b."?column?_1" AS y
FROM ( SELECT 3, 4) b("?column?", "?column?_1")
using the same add-some-digits-until-unique logic we are using for
relation aliases. This could be done by considering all the column
aliases of each RTE when we arrive at it during the recursive scan.
On further reflection I think my worry about the top-level aliases
was unfounded --- we prevent views from being created at all unless
the top-level column names are all distinct. But we definitely
have got issues for lower-level aliases, as these examples show.
regards, tom lane
From | Date | Subject | |
---|---|---|---|
Next Message | Tom Lane | 2012-12-22 03:05:30 | Re: pgcrypto seeding problem when ssl=on |
Previous Message | Noah Misch | 2012-12-22 02:35:58 | Re: Commits 8de72b and 5457a1 (COPY FREEZE) |