mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Allow foreign tables to participate in inheritance.
Foreign tables can now be inheritance children, or parents. Much of the system was already ready for this, but we had to fix a few things of course, mostly in the area of planner and executor handling of row locks. As side effects of this, allow foreign tables to have NOT VALID CHECK constraints (and hence to accept ALTER ... VALIDATE CONSTRAINT), and to accept ALTER SET STORAGE and ALTER SET WITH/WITHOUT OIDS. Continuing to disallow these things would've required bizarre and inconsistent special cases in inheritance behavior. Since foreign tables don't enforce CHECK constraints anyway, a NOT VALID one is a complete no-op, but that doesn't mean we shouldn't allow it. And it's possible that some FDWs might have use for SET STORAGE or SET WITH OIDS, though doubtless they will be no-ops for most. An additional change in support of this is that when a ModifyTable node has multiple target tables, they will all now be explicitly identified in EXPLAIN output, for example: Update on pt1 (cost=0.00..321.05 rows=3541 width=46) Update on pt1 Foreign Update on ft1 Foreign Update on ft2 Update on child3 -> Seq Scan on pt1 (cost=0.00..0.00 rows=1 width=46) -> Foreign Scan on ft1 (cost=100.00..148.03 rows=1170 width=46) -> Foreign Scan on ft2 (cost=100.00..148.03 rows=1170 width=46) -> Seq Scan on child3 (cost=0.00..25.00 rows=1200 width=46) This was done mainly to provide an unambiguous place to attach "Remote SQL" fields, but it is useful for inherited updates even when no foreign tables are involved. Shigeru Hanada and Etsuro Fujita, reviewed by Ashutosh Bapat and Kyotaro Horiguchi, some additional hacking by me
This commit is contained in:
@ -755,6 +755,7 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 OPTIONS (SET p2 'V2', DROP p1);
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 SET STATISTICS 10000;
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 SET (n_distinct = 100);
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STATISTICS -1;
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STORAGE PLAIN;
|
||||
\d+ ft1
|
||||
Foreign table "public.ft1"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
@ -766,7 +767,7 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STATISTICS -1;
|
||||
c5 | integer | | | plain | |
|
||||
c6 | integer | not null | | plain | |
|
||||
c7 | integer | | (p1 'v1', p2 'v2') | plain | |
|
||||
c8 | text | | (p2 'V2') | extended | |
|
||||
c8 | text | | (p2 'V2') | plain | |
|
||||
c9 | integer | | | plain | |
|
||||
c10 | integer | | (p1 'v1') | plain | |
|
||||
Check constraints:
|
||||
@ -784,9 +785,7 @@ ALTER FOREIGN TABLE ft1 ADD PRIMARY KEY (c7); -- ERROR
|
||||
ERROR: primary key constraints are not supported on foreign tables
|
||||
LINE 1: ALTER FOREIGN TABLE ft1 ADD PRIMARY KEY (c7);
|
||||
^
|
||||
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c9_check CHECK (c9 < 0) NOT VALID; -- ERROR
|
||||
ERROR: CHECK constraints on foreign tables cannot be marked NOT VALID
|
||||
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c9_check CHECK (c9 < 0);
|
||||
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c9_check CHECK (c9 < 0) NOT VALID;
|
||||
ALTER FOREIGN TABLE ft1 ALTER CONSTRAINT ft1_c9_check DEFERRABLE; -- ERROR
|
||||
ERROR: "ft1" is not a table
|
||||
ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c9_check;
|
||||
@ -794,8 +793,7 @@ ALTER FOREIGN TABLE ft1 DROP CONSTRAINT no_const; -- ERROR
|
||||
ERROR: constraint "no_const" of relation "ft1" does not exist
|
||||
ALTER FOREIGN TABLE ft1 DROP CONSTRAINT IF EXISTS no_const;
|
||||
NOTICE: constraint "no_const" of relation "ft1" does not exist, skipping
|
||||
ALTER FOREIGN TABLE ft1 SET WITH OIDS; -- ERROR
|
||||
ERROR: "ft1" is not a table
|
||||
ALTER FOREIGN TABLE ft1 SET WITH OIDS;
|
||||
ALTER FOREIGN TABLE ft1 OWNER TO regress_test_role;
|
||||
ALTER FOREIGN TABLE ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@');
|
||||
ALTER FOREIGN TABLE ft1 DROP COLUMN no_column; -- ERROR
|
||||
@ -1234,6 +1232,501 @@ DROP TRIGGER trigtest_before_row ON foreign_schema.foreign_table_1;
|
||||
DROP TRIGGER trigtest_after_stmt ON foreign_schema.foreign_table_1;
|
||||
DROP TRIGGER trigtest_after_row ON foreign_schema.foreign_table_1;
|
||||
DROP FUNCTION dummy_trigger();
|
||||
-- Table inheritance
|
||||
CREATE TABLE pt1 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
);
|
||||
CREATE FOREIGN TABLE ft2 () INHERITS (pt1)
|
||||
SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
DROP FOREIGN TABLE ft2;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
|
||||
CREATE FOREIGN TABLE ft2 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
|
||||
ALTER FOREIGN TABLE ft2 INHERIT pt1;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
CREATE TABLE ct3() INHERITS(ft2);
|
||||
CREATE FOREIGN TABLE ft3 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
) INHERITS(ft2)
|
||||
SERVER s0;
|
||||
NOTICE: merging column "c1" with inherited definition
|
||||
NOTICE: merging column "c2" with inherited definition
|
||||
NOTICE: merging column "c3" with inherited definition
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
Child tables: ct3,
|
||||
ft3
|
||||
|
||||
\d+ ct3
|
||||
Table "public.ct3"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Inherits: ft2
|
||||
|
||||
\d+ ft3
|
||||
Foreign table "public.ft3"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Server: s0
|
||||
Inherits: ft2
|
||||
|
||||
-- add attributes recursively
|
||||
ALTER TABLE pt1 ADD COLUMN c4 integer;
|
||||
ALTER TABLE pt1 ADD COLUMN c5 integer DEFAULT 0;
|
||||
ALTER TABLE pt1 ADD COLUMN c6 integer;
|
||||
ALTER TABLE pt1 ADD COLUMN c7 integer NOT NULL;
|
||||
ALTER TABLE pt1 ADD COLUMN c8 integer;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
c4 | integer | | plain | |
|
||||
c5 | integer | default 0 | plain | |
|
||||
c6 | integer | | plain | |
|
||||
c7 | integer | not null | plain | |
|
||||
c8 | integer | | plain | |
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
c4 | integer | | | plain | |
|
||||
c5 | integer | default 0 | | plain | |
|
||||
c6 | integer | | | plain | |
|
||||
c7 | integer | not null | | plain | |
|
||||
c8 | integer | | | plain | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
Child tables: ct3,
|
||||
ft3
|
||||
|
||||
\d+ ct3
|
||||
Table "public.ct3"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
c4 | integer | | plain | |
|
||||
c5 | integer | default 0 | plain | |
|
||||
c6 | integer | | plain | |
|
||||
c7 | integer | not null | plain | |
|
||||
c8 | integer | | plain | |
|
||||
Inherits: ft2
|
||||
|
||||
\d+ ft3
|
||||
Foreign table "public.ft3"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
c4 | integer | | | plain | |
|
||||
c5 | integer | default 0 | | plain | |
|
||||
c6 | integer | | | plain | |
|
||||
c7 | integer | not null | | plain | |
|
||||
c8 | integer | | | plain | |
|
||||
Server: s0
|
||||
Inherits: ft2
|
||||
|
||||
-- alter attributes recursively
|
||||
ALTER TABLE pt1 ALTER COLUMN c4 SET DEFAULT 0;
|
||||
ALTER TABLE pt1 ALTER COLUMN c5 DROP DEFAULT;
|
||||
ALTER TABLE pt1 ALTER COLUMN c6 SET NOT NULL;
|
||||
ALTER TABLE pt1 ALTER COLUMN c7 DROP NOT NULL;
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 TYPE char(10) USING '0'; -- ERROR
|
||||
ERROR: "ft2" is not a table
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 TYPE char(10);
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 SET DATA TYPE text;
|
||||
ALTER TABLE pt1 ALTER COLUMN c1 SET STATISTICS 10000;
|
||||
ALTER TABLE pt1 ALTER COLUMN c1 SET (n_distinct = 100);
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 SET STATISTICS -1;
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 SET STORAGE EXTERNAL;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
c4 | integer | default 0 | plain | |
|
||||
c5 | integer | | plain | |
|
||||
c6 | integer | not null | plain | |
|
||||
c7 | integer | | plain | |
|
||||
c8 | text | | external | |
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | 10000 |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
c4 | integer | default 0 | | plain | |
|
||||
c5 | integer | | | plain | |
|
||||
c6 | integer | not null | | plain | |
|
||||
c7 | integer | | | plain | |
|
||||
c8 | text | | | external | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
Child tables: ct3,
|
||||
ft3
|
||||
|
||||
-- drop attributes recursively
|
||||
ALTER TABLE pt1 DROP COLUMN c4;
|
||||
ALTER TABLE pt1 DROP COLUMN c5;
|
||||
ALTER TABLE pt1 DROP COLUMN c6;
|
||||
ALTER TABLE pt1 DROP COLUMN c7;
|
||||
ALTER TABLE pt1 DROP COLUMN c8;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | 10000 |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
Child tables: ct3,
|
||||
ft3
|
||||
|
||||
-- add constraints recursively
|
||||
ALTER TABLE pt1 ADD CONSTRAINT pt1chk1 CHECK (c1 > 0) NO INHERIT;
|
||||
ALTER TABLE pt1 ADD CONSTRAINT pt1chk2 CHECK (c2 <> '');
|
||||
-- connoinherit should be true for NO INHERIT constraint
|
||||
SELECT relname, conname, contype, conislocal, coninhcount, connoinherit
|
||||
FROM pg_class AS pc JOIN pg_constraint AS pgc ON (conrelid = pc.oid)
|
||||
WHERE pc.relname = 'pt1'
|
||||
ORDER BY 1,2;
|
||||
relname | conname | contype | conislocal | coninhcount | connoinherit
|
||||
---------+---------+---------+------------+-------------+--------------
|
||||
pt1 | pt1chk1 | c | t | 0 | t
|
||||
pt1 | pt1chk2 | c | t | 0 | f
|
||||
(2 rows)
|
||||
|
||||
-- child does not inherit NO INHERIT constraints
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk1" CHECK (c1 > 0) NO INHERIT
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | 10000 |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
Child tables: ct3,
|
||||
ft3
|
||||
|
||||
DROP FOREIGN TABLE ft2; -- ERROR
|
||||
ERROR: cannot drop foreign table ft2 because other objects depend on it
|
||||
DETAIL: table ct3 depends on foreign table ft2
|
||||
foreign table ft3 depends on foreign table ft2
|
||||
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
||||
DROP FOREIGN TABLE ft2 CASCADE;
|
||||
NOTICE: drop cascades to 2 other objects
|
||||
DETAIL: drop cascades to table ct3
|
||||
drop cascades to foreign table ft3
|
||||
CREATE FOREIGN TABLE ft2 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
|
||||
-- child must have parent's INHERIT constraints
|
||||
ALTER FOREIGN TABLE ft2 INHERIT pt1; -- ERROR
|
||||
ERROR: child table is missing constraint "pt1chk2"
|
||||
ALTER FOREIGN TABLE ft2 ADD CONSTRAINT pt1chk2 CHECK (c2 <> '');
|
||||
ALTER FOREIGN TABLE ft2 INHERIT pt1;
|
||||
-- child does not inherit NO INHERIT constraints
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk1" CHECK (c1 > 0) NO INHERIT
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
-- drop constraints recursively
|
||||
ALTER TABLE pt1 DROP CONSTRAINT pt1chk1 CASCADE;
|
||||
ALTER TABLE pt1 DROP CONSTRAINT pt1chk2 CASCADE;
|
||||
-- NOT VALID case
|
||||
INSERT INTO pt1 VALUES (1, 'pt1'::text, '1994-01-01'::date);
|
||||
ALTER TABLE pt1 ADD CONSTRAINT pt1chk3 CHECK (c2 <> '') NOT VALID;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk3" CHECK (c2 <> ''::text) NOT VALID
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
"pt1chk3" CHECK (c2 <> ''::text) NOT VALID
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
-- VALIDATE CONSTRAINT need do nothing on foreign tables
|
||||
ALTER TABLE pt1 VALIDATE CONSTRAINT pt1chk3;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk3" CHECK (c2 <> ''::text)
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
"pt1chk3" CHECK (c2 <> ''::text)
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
-- OID system column
|
||||
ALTER TABLE pt1 SET WITH OIDS;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk3" CHECK (c2 <> ''::text)
|
||||
Child tables: ft2
|
||||
Has OIDs: yes
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
"pt1chk3" CHECK (c2 <> ''::text)
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
Has OIDs: yes
|
||||
|
||||
ALTER TABLE ft2 SET WITHOUT OIDS; -- ERROR
|
||||
ERROR: cannot drop inherited column "oid"
|
||||
ALTER TABLE pt1 SET WITHOUT OIDS;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
c1 | integer | not null | plain | 10000 |
|
||||
c2 | text | | extended | |
|
||||
c3 | date | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk3" CHECK (c2 <> ''::text)
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
c1 | integer | not null | | plain | |
|
||||
c2 | text | | | extended | |
|
||||
c3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"pt1chk2" CHECK (c2 <> ''::text)
|
||||
"pt1chk3" CHECK (c2 <> ''::text)
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
-- changes name of an attribute recursively
|
||||
ALTER TABLE pt1 RENAME COLUMN c1 TO f1;
|
||||
ALTER TABLE pt1 RENAME COLUMN c2 TO f2;
|
||||
ALTER TABLE pt1 RENAME COLUMN c3 TO f3;
|
||||
-- changes name of a constraint recursively
|
||||
ALTER TABLE pt1 RENAME CONSTRAINT pt1chk3 TO f2_check;
|
||||
\d+ pt1
|
||||
Table "public.pt1"
|
||||
Column | Type | Modifiers | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+--------------+-------------
|
||||
f1 | integer | not null | plain | 10000 |
|
||||
f2 | text | | extended | |
|
||||
f3 | date | | plain | |
|
||||
Check constraints:
|
||||
"f2_check" CHECK (f2 <> ''::text)
|
||||
Child tables: ft2
|
||||
|
||||
\d+ ft2
|
||||
Foreign table "public.ft2"
|
||||
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
|
||||
--------+---------+-----------+-------------+----------+--------------+-------------
|
||||
f1 | integer | not null | | plain | |
|
||||
f2 | text | | | extended | |
|
||||
f3 | date | | | plain | |
|
||||
Check constraints:
|
||||
"f2_check" CHECK (f2 <> ''::text)
|
||||
"pt1chk2" CHECK (f2 <> ''::text)
|
||||
Server: s0
|
||||
FDW Options: (delimiter ',', quote '"', "be quoted" 'value')
|
||||
Inherits: pt1
|
||||
|
||||
-- TRUNCATE doesn't work on foreign tables, either directly or recursively
|
||||
TRUNCATE ft2; -- ERROR
|
||||
ERROR: "ft2" is not a table
|
||||
TRUNCATE pt1; -- ERROR
|
||||
ERROR: "ft2" is not a table
|
||||
DROP TABLE pt1 CASCADE;
|
||||
NOTICE: drop cascades to foreign table ft2
|
||||
-- IMPORT FOREIGN SCHEMA
|
||||
IMPORT FOREIGN SCHEMA s1 FROM SERVER s9 INTO public; -- ERROR
|
||||
ERROR: foreign-data wrapper "foo" has no handler
|
||||
|
@ -1037,6 +1037,9 @@ EXPLAIN (COSTS OFF) UPDATE t1 SET b = b || b WHERE f_leak(b);
|
||||
QUERY PLAN
|
||||
-------------------------------------------
|
||||
Update on t1 t1_3
|
||||
Update on t1 t1_3
|
||||
Update on t2 t1
|
||||
Update on t3 t1
|
||||
-> Subquery Scan on t1
|
||||
Filter: f_leak(t1.b)
|
||||
-> LockRows
|
||||
@ -1052,7 +1055,7 @@ EXPLAIN (COSTS OFF) UPDATE t1 SET b = b || b WHERE f_leak(b);
|
||||
-> LockRows
|
||||
-> Seq Scan on t3
|
||||
Filter: ((a % 2) = 0)
|
||||
(16 rows)
|
||||
(19 rows)
|
||||
|
||||
UPDATE t1 SET b = b || b WHERE f_leak(b);
|
||||
NOTICE: f_leak => bbb
|
||||
@ -1149,6 +1152,9 @@ EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b);
|
||||
QUERY PLAN
|
||||
-------------------------------------------
|
||||
Delete on t1 t1_3
|
||||
Delete on t1 t1_3
|
||||
Delete on t2 t1
|
||||
Delete on t3 t1
|
||||
-> Subquery Scan on t1
|
||||
Filter: f_leak(t1.b)
|
||||
-> LockRows
|
||||
@ -1164,7 +1170,7 @@ EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b);
|
||||
-> LockRows
|
||||
-> Seq Scan on t3
|
||||
Filter: ((a % 2) = 0)
|
||||
(16 rows)
|
||||
(19 rows)
|
||||
|
||||
DELETE FROM only t1 WHERE f_leak(b) RETURNING oid, *, t1;
|
||||
NOTICE: f_leak => bbbbbb_updt
|
||||
|
@ -2064,6 +2064,10 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a = 3;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
Update on public.t1 t1_4
|
||||
Update on public.t1 t1_4
|
||||
Update on public.t11 t1
|
||||
Update on public.t12 t1
|
||||
Update on public.t111 t1
|
||||
-> Subquery Scan on t1
|
||||
Output: 100, t1.b, t1.c, t1.ctid
|
||||
Filter: snoop(t1.a)
|
||||
@ -2132,7 +2136,7 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a = 3;
|
||||
-> Seq Scan on public.t111 t111_4
|
||||
Output: t111_4.ctid, t111_4.tableoid, t111_4.a
|
||||
Filter: (t111_4.a = 3)
|
||||
(69 rows)
|
||||
(73 rows)
|
||||
|
||||
UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a = 3;
|
||||
SELECT * FROM v1 WHERE a=100; -- Nothing should have been changed to 100
|
||||
@ -2150,6 +2154,10 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
Update on public.t1 t1_4
|
||||
Update on public.t1 t1_4
|
||||
Update on public.t11 t1
|
||||
Update on public.t12 t1
|
||||
Update on public.t111 t1
|
||||
-> Subquery Scan on t1
|
||||
Output: (t1.a + 1), t1.b, t1.c, t1.ctid
|
||||
Filter: snoop(t1.a)
|
||||
@ -2218,7 +2226,7 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
|
||||
-> Seq Scan on public.t111 t111_4
|
||||
Output: t111_4.ctid, t111_4.tableoid, t111_4.a
|
||||
Filter: (t111_4.a = 8)
|
||||
(69 rows)
|
||||
(73 rows)
|
||||
|
||||
UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
|
||||
NOTICE: snooped value: 8
|
||||
|
@ -2086,6 +2086,10 @@ DELETE FROM a USING wcte WHERE aa = q2;
|
||||
QUERY PLAN
|
||||
------------------------------------------------
|
||||
Delete on public.a
|
||||
Delete on public.a
|
||||
Delete on public.b
|
||||
Delete on public.c
|
||||
Delete on public.d
|
||||
CTE wcte
|
||||
-> Insert on public.int8_tbl
|
||||
Output: int8_tbl.q2
|
||||
@ -2119,7 +2123,7 @@ DELETE FROM a USING wcte WHERE aa = q2;
|
||||
Output: d.ctid, d.aa
|
||||
-> CTE Scan on wcte
|
||||
Output: wcte.*, wcte.q2
|
||||
(34 rows)
|
||||
(38 rows)
|
||||
|
||||
-- error cases
|
||||
-- data-modifying WITH tries to use its own output
|
||||
|
@ -328,19 +328,19 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 OPTIONS (SET p2 'V2', DROP p1);
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 SET STATISTICS 10000;
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 SET (n_distinct = 100);
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STATISTICS -1;
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STORAGE PLAIN;
|
||||
\d+ ft1
|
||||
-- can't change the column type if it's used elsewhere
|
||||
CREATE TABLE use_ft1_column_type (x ft1);
|
||||
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET DATA TYPE integer; -- ERROR
|
||||
DROP TABLE use_ft1_column_type;
|
||||
ALTER FOREIGN TABLE ft1 ADD PRIMARY KEY (c7); -- ERROR
|
||||
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c9_check CHECK (c9 < 0) NOT VALID; -- ERROR
|
||||
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c9_check CHECK (c9 < 0);
|
||||
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c9_check CHECK (c9 < 0) NOT VALID;
|
||||
ALTER FOREIGN TABLE ft1 ALTER CONSTRAINT ft1_c9_check DEFERRABLE; -- ERROR
|
||||
ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c9_check;
|
||||
ALTER FOREIGN TABLE ft1 DROP CONSTRAINT no_const; -- ERROR
|
||||
ALTER FOREIGN TABLE ft1 DROP CONSTRAINT IF EXISTS no_const;
|
||||
ALTER FOREIGN TABLE ft1 SET WITH OIDS; -- ERROR
|
||||
ALTER FOREIGN TABLE ft1 SET WITH OIDS;
|
||||
ALTER FOREIGN TABLE ft1 OWNER TO regress_test_role;
|
||||
ALTER FOREIGN TABLE ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@');
|
||||
ALTER FOREIGN TABLE ft1 DROP COLUMN no_column; -- ERROR
|
||||
@ -536,6 +536,137 @@ DROP TRIGGER trigtest_after_row ON foreign_schema.foreign_table_1;
|
||||
|
||||
DROP FUNCTION dummy_trigger();
|
||||
|
||||
-- Table inheritance
|
||||
CREATE TABLE pt1 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
);
|
||||
CREATE FOREIGN TABLE ft2 () INHERITS (pt1)
|
||||
SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
DROP FOREIGN TABLE ft2;
|
||||
\d+ pt1
|
||||
CREATE FOREIGN TABLE ft2 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
|
||||
\d+ ft2
|
||||
ALTER FOREIGN TABLE ft2 INHERIT pt1;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
CREATE TABLE ct3() INHERITS(ft2);
|
||||
CREATE FOREIGN TABLE ft3 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
) INHERITS(ft2)
|
||||
SERVER s0;
|
||||
\d+ ft2
|
||||
\d+ ct3
|
||||
\d+ ft3
|
||||
|
||||
-- add attributes recursively
|
||||
ALTER TABLE pt1 ADD COLUMN c4 integer;
|
||||
ALTER TABLE pt1 ADD COLUMN c5 integer DEFAULT 0;
|
||||
ALTER TABLE pt1 ADD COLUMN c6 integer;
|
||||
ALTER TABLE pt1 ADD COLUMN c7 integer NOT NULL;
|
||||
ALTER TABLE pt1 ADD COLUMN c8 integer;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
\d+ ct3
|
||||
\d+ ft3
|
||||
|
||||
-- alter attributes recursively
|
||||
ALTER TABLE pt1 ALTER COLUMN c4 SET DEFAULT 0;
|
||||
ALTER TABLE pt1 ALTER COLUMN c5 DROP DEFAULT;
|
||||
ALTER TABLE pt1 ALTER COLUMN c6 SET NOT NULL;
|
||||
ALTER TABLE pt1 ALTER COLUMN c7 DROP NOT NULL;
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 TYPE char(10) USING '0'; -- ERROR
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 TYPE char(10);
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 SET DATA TYPE text;
|
||||
ALTER TABLE pt1 ALTER COLUMN c1 SET STATISTICS 10000;
|
||||
ALTER TABLE pt1 ALTER COLUMN c1 SET (n_distinct = 100);
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 SET STATISTICS -1;
|
||||
ALTER TABLE pt1 ALTER COLUMN c8 SET STORAGE EXTERNAL;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
|
||||
-- drop attributes recursively
|
||||
ALTER TABLE pt1 DROP COLUMN c4;
|
||||
ALTER TABLE pt1 DROP COLUMN c5;
|
||||
ALTER TABLE pt1 DROP COLUMN c6;
|
||||
ALTER TABLE pt1 DROP COLUMN c7;
|
||||
ALTER TABLE pt1 DROP COLUMN c8;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
|
||||
-- add constraints recursively
|
||||
ALTER TABLE pt1 ADD CONSTRAINT pt1chk1 CHECK (c1 > 0) NO INHERIT;
|
||||
ALTER TABLE pt1 ADD CONSTRAINT pt1chk2 CHECK (c2 <> '');
|
||||
-- connoinherit should be true for NO INHERIT constraint
|
||||
SELECT relname, conname, contype, conislocal, coninhcount, connoinherit
|
||||
FROM pg_class AS pc JOIN pg_constraint AS pgc ON (conrelid = pc.oid)
|
||||
WHERE pc.relname = 'pt1'
|
||||
ORDER BY 1,2;
|
||||
-- child does not inherit NO INHERIT constraints
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
DROP FOREIGN TABLE ft2; -- ERROR
|
||||
DROP FOREIGN TABLE ft2 CASCADE;
|
||||
CREATE FOREIGN TABLE ft2 (
|
||||
c1 integer NOT NULL,
|
||||
c2 text,
|
||||
c3 date
|
||||
) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
|
||||
-- child must have parent's INHERIT constraints
|
||||
ALTER FOREIGN TABLE ft2 INHERIT pt1; -- ERROR
|
||||
ALTER FOREIGN TABLE ft2 ADD CONSTRAINT pt1chk2 CHECK (c2 <> '');
|
||||
ALTER FOREIGN TABLE ft2 INHERIT pt1;
|
||||
-- child does not inherit NO INHERIT constraints
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
|
||||
-- drop constraints recursively
|
||||
ALTER TABLE pt1 DROP CONSTRAINT pt1chk1 CASCADE;
|
||||
ALTER TABLE pt1 DROP CONSTRAINT pt1chk2 CASCADE;
|
||||
|
||||
-- NOT VALID case
|
||||
INSERT INTO pt1 VALUES (1, 'pt1'::text, '1994-01-01'::date);
|
||||
ALTER TABLE pt1 ADD CONSTRAINT pt1chk3 CHECK (c2 <> '') NOT VALID;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
-- VALIDATE CONSTRAINT need do nothing on foreign tables
|
||||
ALTER TABLE pt1 VALIDATE CONSTRAINT pt1chk3;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
|
||||
-- OID system column
|
||||
ALTER TABLE pt1 SET WITH OIDS;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
ALTER TABLE ft2 SET WITHOUT OIDS; -- ERROR
|
||||
ALTER TABLE pt1 SET WITHOUT OIDS;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
|
||||
-- changes name of an attribute recursively
|
||||
ALTER TABLE pt1 RENAME COLUMN c1 TO f1;
|
||||
ALTER TABLE pt1 RENAME COLUMN c2 TO f2;
|
||||
ALTER TABLE pt1 RENAME COLUMN c3 TO f3;
|
||||
-- changes name of a constraint recursively
|
||||
ALTER TABLE pt1 RENAME CONSTRAINT pt1chk3 TO f2_check;
|
||||
\d+ pt1
|
||||
\d+ ft2
|
||||
|
||||
-- TRUNCATE doesn't work on foreign tables, either directly or recursively
|
||||
TRUNCATE ft2; -- ERROR
|
||||
TRUNCATE pt1; -- ERROR
|
||||
|
||||
DROP TABLE pt1 CASCADE;
|
||||
|
||||
-- IMPORT FOREIGN SCHEMA
|
||||
IMPORT FOREIGN SCHEMA s1 FROM SERVER s9 INTO public; -- ERROR
|
||||
IMPORT FOREIGN SCHEMA s1 LIMIT TO (t1) FROM SERVER s9 INTO public; --ERROR
|
||||
|
Reference in New Issue
Block a user