mirror of
https://github.com/postgres/postgres.git
synced 2025-11-26 23:43:30 +03:00
Replace pg_attribute.attisinherited with attislocal and attinhcount
columns, to allow more correct behavior in multiple-inheritance cases. Patch by Alvaro Herrera, review by Tom Lane.
This commit is contained in:
@@ -1054,3 +1054,116 @@ alter table renameColumn add column w int;
|
||||
-- this should fail
|
||||
alter table only renameColumn add column x int;
|
||||
ERROR: Attribute must be added to child tables too
|
||||
-- Test corner cases in dropping of inherited columns
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 (f1 int not null) inherits(p1);
|
||||
NOTICE: CREATE TABLE: merging attribute "f1" with inherited definition
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
ERROR: ALTER TABLE: Cannot drop inherited column "f1"
|
||||
-- should work
|
||||
alter table p1 drop column f1;
|
||||
-- c1.f1 is still there, but no longer inherited
|
||||
select f1 from c1;
|
||||
f1
|
||||
----
|
||||
(0 rows)
|
||||
|
||||
alter table c1 drop column f1;
|
||||
select f1 from c1;
|
||||
ERROR: Attribute "f1" not found
|
||||
drop table p1 cascade;
|
||||
NOTICE: Drop cascades to table c1
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 () inherits(p1);
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
ERROR: ALTER TABLE: Cannot drop inherited column "f1"
|
||||
alter table p1 drop column f1;
|
||||
-- c1.f1 is dropped now, since there is no local definition for it
|
||||
select f1 from c1;
|
||||
ERROR: Attribute "f1" not found
|
||||
drop table p1 cascade;
|
||||
NOTICE: Drop cascades to table c1
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 () inherits(p1);
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
ERROR: ALTER TABLE: Cannot drop inherited column "f1"
|
||||
alter table only p1 drop column f1;
|
||||
-- c1.f1 is NOT dropped, but must now be considered non-inherited
|
||||
alter table c1 drop column f1;
|
||||
drop table p1 cascade;
|
||||
NOTICE: Drop cascades to table c1
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 (f1 int not null) inherits(p1);
|
||||
NOTICE: CREATE TABLE: merging attribute "f1" with inherited definition
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
ERROR: ALTER TABLE: Cannot drop inherited column "f1"
|
||||
alter table only p1 drop column f1;
|
||||
-- c1.f1 is still there, but no longer inherited
|
||||
alter table c1 drop column f1;
|
||||
drop table p1 cascade;
|
||||
NOTICE: Drop cascades to table c1
|
||||
create table p1(id int, name text);
|
||||
create table p2(id2 int, name text, height int);
|
||||
create table c1(age int) inherits(p1,p2);
|
||||
NOTICE: CREATE TABLE: merging multiple inherited definitions of attribute "name"
|
||||
create table gc1() inherits (c1);
|
||||
select relname, attname, attinhcount, attislocal
|
||||
from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
|
||||
where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
|
||||
order by relname, attnum;
|
||||
relname | attname | attinhcount | attislocal
|
||||
---------+---------+-------------+------------
|
||||
c1 | id | 1 | f
|
||||
c1 | name | 2 | f
|
||||
c1 | id2 | 1 | f
|
||||
c1 | height | 1 | f
|
||||
c1 | age | 0 | t
|
||||
gc1 | id | 1 | f
|
||||
gc1 | name | 1 | f
|
||||
gc1 | id2 | 1 | f
|
||||
gc1 | height | 1 | f
|
||||
gc1 | age | 1 | f
|
||||
p1 | id | 0 | t
|
||||
p1 | name | 0 | t
|
||||
p2 | id2 | 0 | t
|
||||
p2 | name | 0 | t
|
||||
p2 | height | 0 | t
|
||||
(15 rows)
|
||||
|
||||
-- should work
|
||||
alter table only p1 drop column name;
|
||||
-- should work. Now c1.name is local and inhcount is 0.
|
||||
alter table p2 drop column name;
|
||||
-- should be rejected since its inherited
|
||||
alter table gc1 drop column name;
|
||||
ERROR: ALTER TABLE: Cannot drop inherited column "name"
|
||||
-- should work, and drop gc1.name along
|
||||
alter table c1 drop column name;
|
||||
-- should fail: column does not exist
|
||||
alter table gc1 drop column name;
|
||||
ERROR: Relation "gc1" has no column "name"
|
||||
-- should work and drop the attribute in all tables
|
||||
alter table p2 drop column height;
|
||||
select relname, attname, attinhcount, attislocal
|
||||
from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
|
||||
where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
|
||||
order by relname, attnum;
|
||||
relname | attname | attinhcount | attislocal
|
||||
---------+---------+-------------+------------
|
||||
c1 | id | 1 | f
|
||||
c1 | id2 | 1 | f
|
||||
c1 | age | 0 | t
|
||||
gc1 | id | 1 | f
|
||||
gc1 | id2 | 1 | f
|
||||
gc1 | age | 1 | f
|
||||
p1 | id | 0 | t
|
||||
p2 | id2 | 0 | t
|
||||
(8 rows)
|
||||
|
||||
drop table p1, p2 cascade;
|
||||
NOTICE: Drop cascades to table c1
|
||||
NOTICE: Drop cascades to table gc1
|
||||
|
||||
@@ -170,7 +170,8 @@ WHERE (p1.relkind = 'i' AND p1.relam = 0) OR
|
||||
SELECT p1.attrelid, p1.attname
|
||||
FROM pg_attribute as p1
|
||||
WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
|
||||
p1.attcacheoff != -1;
|
||||
p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
|
||||
(p1.attinhcount = 0 AND NOT p1.attislocal);
|
||||
attrelid | attname
|
||||
----------+---------
|
||||
(0 rows)
|
||||
|
||||
@@ -764,3 +764,83 @@ alter table renameColumn add column w int;
|
||||
|
||||
-- this should fail
|
||||
alter table only renameColumn add column x int;
|
||||
|
||||
|
||||
-- Test corner cases in dropping of inherited columns
|
||||
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 (f1 int not null) inherits(p1);
|
||||
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
-- should work
|
||||
alter table p1 drop column f1;
|
||||
-- c1.f1 is still there, but no longer inherited
|
||||
select f1 from c1;
|
||||
alter table c1 drop column f1;
|
||||
select f1 from c1;
|
||||
|
||||
drop table p1 cascade;
|
||||
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 () inherits(p1);
|
||||
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
alter table p1 drop column f1;
|
||||
-- c1.f1 is dropped now, since there is no local definition for it
|
||||
select f1 from c1;
|
||||
|
||||
drop table p1 cascade;
|
||||
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 () inherits(p1);
|
||||
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
alter table only p1 drop column f1;
|
||||
-- c1.f1 is NOT dropped, but must now be considered non-inherited
|
||||
alter table c1 drop column f1;
|
||||
|
||||
drop table p1 cascade;
|
||||
|
||||
create table p1 (f1 int, f2 int);
|
||||
create table c1 (f1 int not null) inherits(p1);
|
||||
|
||||
-- should be rejected since c1.f1 is inherited
|
||||
alter table c1 drop column f1;
|
||||
alter table only p1 drop column f1;
|
||||
-- c1.f1 is still there, but no longer inherited
|
||||
alter table c1 drop column f1;
|
||||
|
||||
drop table p1 cascade;
|
||||
|
||||
create table p1(id int, name text);
|
||||
create table p2(id2 int, name text, height int);
|
||||
create table c1(age int) inherits(p1,p2);
|
||||
create table gc1() inherits (c1);
|
||||
|
||||
select relname, attname, attinhcount, attislocal
|
||||
from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
|
||||
where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
|
||||
order by relname, attnum;
|
||||
|
||||
-- should work
|
||||
alter table only p1 drop column name;
|
||||
-- should work. Now c1.name is local and inhcount is 0.
|
||||
alter table p2 drop column name;
|
||||
-- should be rejected since its inherited
|
||||
alter table gc1 drop column name;
|
||||
-- should work, and drop gc1.name along
|
||||
alter table c1 drop column name;
|
||||
-- should fail: column does not exist
|
||||
alter table gc1 drop column name;
|
||||
-- should work and drop the attribute in all tables
|
||||
alter table p2 drop column height;
|
||||
|
||||
select relname, attname, attinhcount, attislocal
|
||||
from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
|
||||
where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
|
||||
order by relname, attnum;
|
||||
|
||||
drop table p1, p2 cascade;
|
||||
|
||||
@@ -137,7 +137,8 @@ WHERE (p1.relkind = 'i' AND p1.relam = 0) OR
|
||||
SELECT p1.attrelid, p1.attname
|
||||
FROM pg_attribute as p1
|
||||
WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
|
||||
p1.attcacheoff != -1;
|
||||
p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
|
||||
(p1.attinhcount = 0 AND NOT p1.attislocal);
|
||||
|
||||
-- Cross-check attnum against parent relation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user