-- -- PUBLICATION -- CREATE ROLE regress_publication_user LOGIN SUPERUSER; CREATE ROLE regress_publication_user2; CREATE ROLE regress_publication_user_dummy LOGIN NOSUPERUSER; SET SESSION AUTHORIZATION 'regress_publication_user';
-- suppress warning that depends on wal_level SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_default;
RESET client_min_messages;
COMMENT ON PUBLICATION testpub_default IS'test publication'; SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p;
SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_ins_trunct WITH (publish = insert);
RESET client_min_messages;
ALTER PUBLICATION testpub_default SET (publish = update);
-- error cases CREATE PUBLICATION testpub_xxx WITH (foo); CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum'); CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0'); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = stored, publish_generated_columns = none); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns);
\dRp
ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete');
\dRp
--- adding tables CREATESCHEMA pub_test; CREATETABLE testpub_tbl1 (id serial primarykey, data text); CREATETABLE pub_test.testpub_nopk (foo int, bar int); CREATE VIEW testpub_view ASSELECT1; CREATETABLE testpub_parted (a int) PARTITION BY LIST (a);
SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_foralltables FORALL TABLES WITH (publish = 'insert');
RESET client_min_messages; ALTER PUBLICATION testpub_foralltables SET (publish = 'insert, update');
CREATETABLE testpub_tbl2 (id serial primarykey, data text); -- fail - can't add to for all tables publication ALTER PUBLICATION testpub_foralltables ADDTABLE testpub_tbl2; -- fail - can't drop from all tables publication ALTER PUBLICATION testpub_foralltables DROPTABLE testpub_tbl2; -- fail - can't add to for all tables publication ALTER PUBLICATION testpub_foralltables SETTABLE pub_test.testpub_nopk;
-- fail - can't add schema to 'FOR ALL TABLES' publication ALTER PUBLICATION testpub_foralltables ADD TABLES INSCHEMA pub_test; -- fail - can't drop schema from 'FOR ALL TABLES' publication ALTER PUBLICATION testpub_foralltables DROP TABLES INSCHEMA pub_test; -- fail - can't set schema to 'FOR ALL TABLES' publication ALTER PUBLICATION testpub_foralltables SET TABLES INSCHEMA pub_test;
SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_fortable FORTABLE testpub_tbl1;
RESET client_min_messages; -- should be able to add schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable ADD TABLES INSCHEMA pub_test;
\dRp+ testpub_fortable -- should be able to drop schema from 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable DROP TABLES INSCHEMA pub_test;
\dRp+ testpub_fortable -- should be able to set schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable SET TABLES INSCHEMA pub_test;
\dRp+ testpub_fortable
SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_forschema FOR TABLES INSCHEMA pub_test; -- should be able to create publication with schema and table of the same -- schema CREATE PUBLICATION testpub_for_tbl_schema FOR TABLES INSCHEMA pub_test, TABLE pub_test.testpub_nopk;
RESET client_min_messages;
\dRp+ testpub_for_tbl_schema
-- weird parser corner case CREATE PUBLICATION testpub_parsertst FORTABLE pub_test.testpub_nopk, CURRENT_SCHEMA; CREATE PUBLICATION testpub_parsertst FOR TABLES INSCHEMA foo, test.foo;
-- should be able to add a table of the same schema to the schema publication ALTER PUBLICATION testpub_forschema ADDTABLE pub_test.testpub_nopk;
\dRp+ testpub_forschema
-- should be able to drop the table ALTER PUBLICATION testpub_forschema DROPTABLE pub_test.testpub_nopk;
\dRp+ testpub_forschema
-- fail - can't drop a table from the schema publication which isn't in the -- publication ALTER PUBLICATION testpub_forschema DROPTABLE pub_test.testpub_nopk; -- should be able to set table to schema publication ALTER PUBLICATION testpub_forschema SETTABLE pub_test.testpub_nopk;
\dRp+ testpub_forschema
SELECT pubname, puballtables FROM pg_publication WHERE pubname = 'testpub_foralltables';
\d+ testpub_tbl2
\dRp+ testpub_foralltables
DROPTABLE testpub_tbl2; DROP PUBLICATION testpub_foralltables, testpub_fortable, testpub_forschema, testpub_for_tbl_schema;
DROPTABLE testpub_tbl3, testpub_tbl3a; DROP PUBLICATION testpub3, testpub4;
-- Tests for partitioned tables SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_forparted; CREATE PUBLICATION testpub_forparted1;
RESET client_min_messages; CREATETABLE testpub_parted1 (LIKE testpub_parted); CREATETABLE testpub_parted2 (LIKE testpub_parted); ALTER PUBLICATION testpub_forparted1 SET (publish='insert'); ALTERTABLE testpub_parted ATTACH PARTITION testpub_parted1 FORVALUESIN (1); ALTERTABLE testpub_parted ATTACH PARTITION testpub_parted2 FORVALUESIN (2); -- works despite missing REPLICA IDENTITY, because updates are not replicated UPDATE testpub_parted1 SET a = 1; -- only parent is listed as being in publication, not the partition ALTER PUBLICATION testpub_forparted ADDTABLE testpub_parted;
\dRp+ testpub_forparted -- works despite missing REPLICA IDENTITY, because no actual update happened UPDATE testpub_parted SET a = 1WHEREfalse; -- should now fail, because parent's publication replicates updates UPDATE testpub_parted1 SET a = 1; ALTERTABLE testpub_parted DETACH PARTITION testpub_parted1; -- works again, because parent's publication is no longer considered UPDATE testpub_parted1 SET a = 1; ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true);
\dRp+ testpub_forparted -- still fail, because parent's publication replicates updates UPDATE testpub_parted2 SET a = 2; ALTER PUBLICATION testpub_forparted DROPTABLE testpub_parted; -- works again, because update is no longer replicated UPDATE testpub_parted2 SET a = 2; DROPTABLE testpub_parted1, testpub_parted2; DROP PUBLICATION testpub_forparted, testpub_forparted1;
-- Tests for row filters CREATETABLE testpub_rf_tbl1 (a integer, b text); CREATETABLE testpub_rf_tbl2 (c text, d integer); CREATETABLE testpub_rf_tbl3 (e integer); CREATETABLE testpub_rf_tbl4 (g text); CREATETABLE testpub_rf_tbl5 (a xml); CREATESCHEMA testpub_rf_schema1; CREATETABLE testpub_rf_schema1.testpub_rf_tbl5 (h integer); CREATESCHEMA testpub_rf_schema2; CREATETABLE testpub_rf_schema2.testpub_rf_tbl6 (i integer); SET client_min_messages = 'ERROR'; -- Firstly, test using the option publish='insert' because the row filter -- validation of referenced columns is less strict than for delete/update. CREATE PUBLICATION testpub5 FORTABLE testpub_rf_tbl1, testpub_rf_tbl2 WHERE (c <> 'test'ANDd < 5) WITH (publish = 'insert');
RESET client_min_messages;
\dRp+ testpub5
\d testpub_rf_tbl3 ALTER PUBLICATION testpub5 ADDTABLE testpub_rf_tbl3 WHERE (e > 1000AND e < 2000);
\dRp+ testpub5
\d testpub_rf_tbl3 ALTER PUBLICATION testpub5 DROPTABLE testpub_rf_tbl2;
\dRp+ testpub5 -- remove testpub_rf_tbl1 and add testpub_rf_tbl3 again (another WHERE expression) ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl3 WHERE (e > 300AND e < 500);
\dRp+ testpub5
\d testpub_rf_tbl3 -- test \d <tablename> (now it displays filter information) SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_rf_yes FORTABLE testpub_rf_tbl1 WHERE (a > 1) WITH (publish = 'insert'); CREATE PUBLICATION testpub_rf_no FORTABLE testpub_rf_tbl1;
RESET client_min_messages;
\d testpub_rf_tbl1 DROP PUBLICATION testpub_rf_yes, testpub_rf_no; -- some more syntax tests to exercise other parser pathways SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax1 FORTABLE testpub_rf_tbl1, ONLY testpub_rf_tbl3 WHERE(e < 999) WITH (publish = 'insert');
RESET client_min_messages;
\dRp+ testpub_syntax1 DROP PUBLICATION testpub_syntax1; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax2 FORTABLE testpub_rf_tbl1, testpub_rf_schema1.testpub_rf_tbl5 WHERE (h < 999) WITH (publish = 'insert');
RESET client_min_messages;
\dRp+ testpub_syntax2 DROP PUBLICATION testpub_syntax2; -- fail - schemas don't allow WHERE clause SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax3 FOR TABLES INSCHEMA testpub_rf_schema1 WHERE (a = 123); CREATE PUBLICATION testpub_syntax3 FOR TABLES INSCHEMA testpub_rf_schema1, testpub_rf_schema1 WHERE (a = 123);
RESET client_min_messages; -- fail - duplicate tables are not allowed if that table has any WHERE clause SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_dups FORTABLE testpub_rf_tbl1 WHERE (a = 1), testpub_rf_tbl1 WITH (publish = 'insert'); CREATE PUBLICATION testpub_dups FORTABLE testpub_rf_tbl1, testpub_rf_tbl1 WHERE (a = 2) WITH (publish = 'insert');
RESET client_min_messages; -- fail - publication WHERE clause must be boolean ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl3 WHERE (1234); -- fail - aggregate functions not allowed in WHERE clause ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl3 WHERE (e < AVG(e)); -- fail - user-defined operators are not allowed CREATE FUNCTION testpub_rf_func1(integer, integer) RETURNS boolean AS $$ SELECT hashint4($1) > $2 $$ LANGUAGE SQL; CREATE OPERATOR =#> (PROCEDURE = testpub_rf_func1, LEFTARG = integer, RIGHTARG = integer); CREATE PUBLICATION testpub6 FORTABLE testpub_rf_tbl3 WHERE (e =#> 27); -- fail - user-defined functions are not allowed CREATE FUNCTION testpub_rf_func2() RETURNS integer IMMUTABLE AS $$ BEGIN RETURN123; END; $$ LANGUAGE plpgsql; ALTER PUBLICATION testpub5 ADDTABLE testpub_rf_tbl1 WHERE (a >= testpub_rf_func2()); -- fail - non-immutable functions are not allowed. random() is volatile. ALTER PUBLICATION testpub5 ADDTABLE testpub_rf_tbl1 WHERE (a < random()); -- fail - user-defined collations are not allowed CREATE COLLATION user_collation FROM"C"; ALTER PUBLICATION testpub5 ADDTABLE testpub_rf_tbl1 WHERE (b < '2'COLLATE user_collation); -- ok - NULLIF is allowed ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (NULLIF(1,2) = a); -- ok - built-in operators are allowed ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (a ISNULL); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE ((a > 5) ISFALSE); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (a ISDISTINCTFROM5); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE ((a, a + 1) < (2, 3)); -- ok - built-in type coercions between two binary compatible datatypes are allowed ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (b::varchar < '2'); -- ok - immutable built-in functions are allowed ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl4 WHERE (length(g) < 6); -- fail - user-defined types are not allowed CREATE TYPE rf_bug_status AS ENUM ('new', 'open', 'closed'); CREATETABLE rf_bug (id serial, description text, status rf_bug_status); CREATE PUBLICATION testpub6 FORTABLE rf_bug WHERE (status = 'open') WITH (publish = 'insert'); DROPTABLE rf_bug; DROP TYPE rf_bug_status; -- fail - row filter expression is not simple CREATE PUBLICATION testpub6 FORTABLE testpub_rf_tbl1 WHERE (a IN (SELECT generate_series(1,5))); -- fail - system columns are not allowed CREATE PUBLICATION testpub6 FORTABLE testpub_rf_tbl1 WHERE ('(0,1)'::tid = ctid); -- ok - conditional expressions are allowed ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl5 WHERE (a IS DOCUMENT); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl5 WHERE (xmlexists('//foo[text() = ''bar'']' PASSING BY VALUE a)); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (NULLIF(1, 2) = a); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (CASE a WHEN5THENtrueELSEfalseEND); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (COALESCE(b, 'foo') = 'foo'); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (GREATEST(a, 10) > 10); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (a IN (2, 4, 6)); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (ARRAY[a] <@ ARRAY[2, 4, 6]); ALTER PUBLICATION testpub5 SETTABLE testpub_rf_tbl1 WHERE (ROW(a, 2) ISNULL); -- fail - WHERE not allowed in DROP ALTER PUBLICATION testpub5 DROPTABLE testpub_rf_tbl1 WHERE (e < 27); -- fail - cannot ALTER SET table which is a member of a pre-existing schema SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub6 FOR TABLES INSCHEMA testpub_rf_schema2; -- should be able to set publication with schema and table of the same schema ALTER PUBLICATION testpub6 SET TABLES INSCHEMA testpub_rf_schema2, TABLE testpub_rf_schema2.testpub_rf_tbl6 WHERE (i < 99);
RESET client_min_messages;
\dRp+ testpub6 -- fail - virtual generated column uses user-defined function -- (Actually, this already fails at CREATE TABLE rather than at CREATE -- PUBLICATION, but let's keep the test in case the former gets -- relaxed sometime.) CREATETABLE testpub_rf_tbl6 (id intPRIMARYKEY, x int, y int GENERATED ALWAYS AS (x * testpub_rf_func2()) VIRTUAL); CREATE PUBLICATION testpub7 FORTABLE testpub_rf_tbl6 WHERE (y > 100); -- test that SET EXPRESSION is rejected, because it could affect a row filter SET client_min_messages = 'ERROR'; CREATETABLE testpub_rf_tbl7 (id intPRIMARYKEY, x int, y int GENERATED ALWAYS AS (x * 111) VIRTUAL); CREATE PUBLICATION testpub8 FORTABLE testpub_rf_tbl7 WHERE (y > 100); ALTERTABLE testpub_rf_tbl7 ALTERCOLUMN y SET EXPRESSION AS (x * testpub_rf_func2());
RESET client_min_messages;
DROPTABLE testpub_rf_tbl1; DROPTABLE testpub_rf_tbl2; DROPTABLE testpub_rf_tbl3; DROPTABLE testpub_rf_tbl4; DROPTABLE testpub_rf_tbl5; --DROP TABLE testpub_rf_tbl6; DROPTABLE testpub_rf_schema1.testpub_rf_tbl5; DROPTABLE testpub_rf_schema2.testpub_rf_tbl6; DROPSCHEMA testpub_rf_schema1; DROPSCHEMA testpub_rf_schema2; DROP PUBLICATION testpub5; DROP PUBLICATION testpub6; DROP PUBLICATION testpub8; DROPTABLE testpub_rf_tbl7; DROP OPERATOR =#>(integer, integer); DROP FUNCTION testpub_rf_func1(integer, integer); DROP FUNCTION testpub_rf_func2(); DROP COLLATION user_collation;
-- ====================================================== -- More row filter tests for validating column references CREATETABLE rf_tbl_abcd_nopk(a int, b int, c int, d int); CREATETABLE rf_tbl_abcd_pk(a int, b int, c int, d int, PRIMARYKEY(a,b)); CREATETABLE rf_tbl_abcd_part_pk (a intPRIMARYKEY, b int) PARTITION by RANGE (a); CREATETABLE rf_tbl_abcd_part_pk_1 (b int, a intPRIMARYKEY); ALTERTABLE rf_tbl_abcd_part_pk ATTACH PARTITION rf_tbl_abcd_part_pk_1 FORVALUESFROM (1) TO (10);
-- Case 1. REPLICA IDENTITY DEFAULT (means use primary key or nothing) -- 1a. REPLICA IDENTITY is DEFAULT and table has a PK. SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub6 FORTABLE rf_tbl_abcd_pk WHERE (a > 99);
RESET client_min_messages; -- ok - "a" is a PK col UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (b > 99); -- ok - "b" is a PK col UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (c > 99); -- fail - "c" is not part of the PK UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (d > 99); -- fail - "d" is not part of the PK UPDATE rf_tbl_abcd_pk SET a = 1; -- 1b. REPLICA IDENTITY is DEFAULT and table has no PK ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk WHERE (a > 99); -- fail - "a" is not part of REPLICA IDENTITY UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Case 2. REPLICA IDENTITY FULL ALTERTABLE rf_tbl_abcd_pk REPLICA IDENTITY FULL; ALTERTABLE rf_tbl_abcd_nopk REPLICA IDENTITY FULL; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (c > 99); -- ok - "c" is in REPLICA IDENTITY now even though not in PK UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk WHERE (a > 99); -- ok - "a" is in REPLICA IDENTITY now UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Case 3. REPLICA IDENTITY NOTHING ALTERTABLE rf_tbl_abcd_pk REPLICA IDENTITY NOTHING; ALTERTABLE rf_tbl_abcd_nopk REPLICA IDENTITY NOTHING; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (a > 99); -- fail - "a" is in PK but it is not part of REPLICA IDENTITY NOTHING UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (c > 99); -- fail - "c" is not in PK and not in REPLICA IDENTITY NOTHING UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk WHERE (a > 99); -- fail - "a" is not in REPLICA IDENTITY NOTHING UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Case 4. REPLICA IDENTITY INDEX ALTERTABLE rf_tbl_abcd_pk ALTERCOLUMN c SETNOTNULL; CREATEUNIQUEINDEX idx_abcd_pk_c ON rf_tbl_abcd_pk(c); ALTERTABLE rf_tbl_abcd_pk REPLICA IDENTITY USINGINDEX idx_abcd_pk_c; ALTERTABLE rf_tbl_abcd_nopk ALTERCOLUMN c SETNOTNULL; CREATEUNIQUEINDEX idx_abcd_nopk_c ON rf_tbl_abcd_nopk(c); ALTERTABLE rf_tbl_abcd_nopk REPLICA IDENTITY USINGINDEX idx_abcd_nopk_c; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (a > 99); -- fail - "a" is in PK but it is not part of REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk WHERE (c > 99); -- ok - "c" is not in PK but it is part of REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk WHERE (a > 99); -- fail - "a" is not in REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_nopk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk WHERE (c > 99); -- ok - "c" is part of REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Tests for partitioned table
-- set PUBLISH_VIA_PARTITION_ROOT to false and test row filter for partitioned -- table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- fail - cannot use row filter for partitioned table ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk WHERE (a > 99); -- ok - can use row filter for partition ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk_1 WHERE (a > 99); -- ok - "a" is a PK col UPDATE rf_tbl_abcd_part_pk SET a = 1; -- set PUBLISH_VIA_PARTITION_ROOT to true and test row filter for partitioned -- table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=1); -- ok - can use row filter for partitioned table ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk WHERE (a > 99); -- ok - "a" is a PK col UPDATE rf_tbl_abcd_part_pk SET a = 1; -- fail - cannot set PUBLISH_VIA_PARTITION_ROOT to false if any row filter is -- used for partitioned table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- remove partitioned table's row filter ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk; -- ok - we don't have row filter for partitioned table. ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- Now change the root filter to use a column "b" -- (which is not in the replica identity) ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk_1 WHERE (b > 99); -- ok - we don't have row filter for partitioned table. ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- fail - "b" is not in REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_part_pk SET a = 1; -- set PUBLISH_VIA_PARTITION_ROOT to true -- can use row filter for partitioned table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=1); -- ok - can use row filter for partitioned table ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk WHERE (b > 99); -- fail - "b" is not in REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_part_pk SET a = 1;
-- ====================================================== -- Tests with generated column SET client_min_messages = 'ERROR';
-- stored CREATETABLE testpub_gencol (a INT, b INT GENERATED ALWAYS AS (a + 1) STORED NOTNULL); CREATEUNIQUEINDEX testpub_gencol_idx ON testpub_gencol (b); ALTERTABLE testpub_gencol REPLICA IDENTITY USINGindex testpub_gencol_idx;
-- error - generated column "b" must be published explicitly as it is -- part of the REPLICA IDENTITY index. CREATE PUBLICATION pub_gencol FORTABLE testpub_gencol; UPDATE testpub_gencol SET a = 100WHERE a = 1;
-- error - generated column "b" must be published explicitly as it is -- part of the REPLICA IDENTITY. ALTERTABLE testpub_gencol REPLICA IDENTITY FULL; UPDATE testpub_gencol SET a = 100WHERE a = 1; DROP PUBLICATION pub_gencol;
-- ok - generated column "b" is published explicitly CREATE PUBLICATION pub_gencol FORTABLE testpub_gencol with (publish_generated_columns = stored); UPDATE testpub_gencol SET a = 100WHERE a = 1; DROP PUBLICATION pub_gencol;
DROPTABLE testpub_gencol;
-- virtual CREATETABLE testpub_gencol (a INT, b INT GENERATED ALWAYS AS (a + 1) VIRTUAL);
-- error - generated column "b" must be published explicitly as it is -- part of the REPLICA IDENTITY. ALTERTABLE testpub_gencol REPLICA IDENTITY FULL; UPDATE testpub_gencol SET a = 100WHERE a = 1; DROP PUBLICATION pub_gencol;
-- error - "stored" setting does not affect virtual column CREATE PUBLICATION pub_gencol FORTABLE testpub_gencol with (publish_generated_columns = stored); UPDATE testpub_gencol SET a = 100WHERE a = 1; DROP PUBLICATION pub_gencol;
-- fail - duplicate tables are not allowed if that table has any column lists SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_dups FORTABLE testpub_tbl1 (a), testpub_tbl1 WITH (publish = 'insert'); CREATE PUBLICATION testpub_dups FORTABLE testpub_tbl1, testpub_tbl1 (a) WITH (publish = 'insert');
RESET client_min_messages;
-- test for column lists SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_fortable FORTABLE testpub_tbl1; CREATE PUBLICATION testpub_fortable_insert WITH (publish = 'insert');
RESET client_min_messages; CREATETABLE testpub_tbl5 (a intPRIMARYKEY, b text, c text,
d int generated always as (a + length(b)) stored,
e int generated always as (a + length(b)) virtual
); -- error: column "x" does not exist ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, x); -- error: replica identity "a" not included in the column list ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (b, c); UPDATE testpub_tbl5 SET a = 1; ALTER PUBLICATION testpub_fortable DROPTABLE testpub_tbl5; -- error: system attributes "ctid" not allowed in column list ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, ctid); ALTER PUBLICATION testpub_fortable SETTABLE testpub_tbl1 (id, ctid); -- error: duplicates not allowed in column list ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, a); ALTER PUBLICATION testpub_fortable SETTABLE testpub_tbl5 (a, a); -- ok ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, c); ALTERTABLE testpub_tbl5 DROPCOLUMN c; -- no dice -- ok: for insert-only publication, any column list is acceptable ALTER PUBLICATION testpub_fortable_insert ADDTABLE testpub_tbl5 (b, c);
/* not all replica identities are good enough */ CREATEUNIQUEINDEX testpub_tbl5_b_key ON testpub_tbl5 (b, c); ALTERTABLE testpub_tbl5 ALTER b SETNOTNULL, ALTER c SETNOTNULL; ALTERTABLE testpub_tbl5 REPLICA IDENTITY USINGINDEX testpub_tbl5_b_key; -- error: replica identity (b,c) is not covered by column list (a, c) UPDATE testpub_tbl5 SET a = 1; ALTER PUBLICATION testpub_fortable DROPTABLE testpub_tbl5;
-- ok: stored generated column "d" can be in the list too ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, d); ALTER PUBLICATION testpub_fortable DROPTABLE testpub_tbl5; -- error: virtual generated column "e" can't be in list ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, e);
-- error: change the replica identity to "b", and column list to (a, c) -- then update fails, because (a, c) does not cover replica identity ALTERTABLE testpub_tbl5 REPLICA IDENTITY USINGINDEX testpub_tbl5_b_key; ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5 (a, c); UPDATE testpub_tbl5 SET a = 1;
/* But if upd/del are not published, it works OK */ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_table_ins WITH (publish = 'insert, truncate');
RESET client_min_messages; ALTER PUBLICATION testpub_table_ins ADDTABLE testpub_tbl5 (a); -- ok
\dRp+ testpub_table_ins
-- error: cannot work with deferrable primary keys CREATETABLE testpub_tbl5d (a intPRIMARYKEY DEFERRABLE); ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl5d; UPDATE testpub_tbl5d SET a = 1; /* but works fine with FULL replica identity */ ALTERTABLE testpub_tbl5d REPLICA IDENTITY FULL; UPDATE testpub_tbl5d SET a = 1; DROPTABLE testpub_tbl5d;
-- tests with REPLICA IDENTITY FULL CREATETABLE testpub_tbl6 (a int, b text, c text); ALTERTABLE testpub_tbl6 REPLICA IDENTITY FULL;
ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl6 (a, b, c); UPDATE testpub_tbl6 SET a = 1; ALTER PUBLICATION testpub_fortable DROPTABLE testpub_tbl6;
ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl6; -- ok UPDATE testpub_tbl6 SET a = 1;
-- make sure changing the column list is propagated to the catalog CREATETABLE testpub_tbl7 (a intprimarykey, b text, c text); ALTER PUBLICATION testpub_fortable ADDTABLE testpub_tbl7 (a, b);
\d+ testpub_tbl7 -- ok: the column list is the same, we should skip this table (or at least not fail) ALTER PUBLICATION testpub_fortable SETTABLE testpub_tbl7 (a, b);
\d+ testpub_tbl7 -- ok: the column list changes, make sure the catalog gets updated ALTER PUBLICATION testpub_fortable SETTABLE testpub_tbl7 (a, c);
\d+ testpub_tbl7
-- column list for partitioned tables has to cover replica identities for -- all child relations CREATETABLE testpub_tbl8 (a int, b text, c text) PARTITION BY HASH (a); -- first partition has replica identity "a" CREATETABLE testpub_tbl8_0 PARTITION OF testpub_tbl8 FORVALUESWITH (modulus 2, remainder 0); ALTERTABLE testpub_tbl8_0 ADDPRIMARYKEY (a); ALTERTABLE testpub_tbl8_0 REPLICA IDENTITY USINGINDEX testpub_tbl8_0_pkey; -- second partition has replica identity "b" CREATETABLE testpub_tbl8_1 PARTITION OF testpub_tbl8 FORVALUESWITH (modulus 2, remainder 1); ALTERTABLE testpub_tbl8_1 ADDPRIMARYKEY (b); ALTERTABLE testpub_tbl8_1 REPLICA IDENTITY USINGINDEX testpub_tbl8_1_pkey;
-- ok: column list covers both "a" and "b" SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_col_list FORTABLE testpub_tbl8 (a, b) WITH (publish_via_partition_root = 'true');
RESET client_min_messages;
-- ok: the same thing, but try plain ADD TABLE ALTER PUBLICATION testpub_col_list DROPTABLE testpub_tbl8; ALTER PUBLICATION testpub_col_list ADDTABLE testpub_tbl8 (a, b); UPDATE testpub_tbl8 SET a = 1;
-- failure: column list does not cover replica identity for the second partition ALTER PUBLICATION testpub_col_list DROPTABLE testpub_tbl8; ALTER PUBLICATION testpub_col_list ADDTABLE testpub_tbl8 (a, c); UPDATE testpub_tbl8 SET a = 1; ALTER PUBLICATION testpub_col_list DROPTABLE testpub_tbl8;
-- failure: one of the partitions has REPLICA IDENTITY FULL ALTERTABLE testpub_tbl8_1 REPLICA IDENTITY FULL; ALTER PUBLICATION testpub_col_list ADDTABLE testpub_tbl8 (a, c); UPDATE testpub_tbl8 SET a = 1; ALTER PUBLICATION testpub_col_list DROPTABLE testpub_tbl8;
-- add table and then try changing replica identity ALTERTABLE testpub_tbl8_1 REPLICA IDENTITY USINGINDEX testpub_tbl8_1_pkey; ALTER PUBLICATION testpub_col_list ADDTABLE testpub_tbl8 (a, b);
-- failure: replica identity full can't be used with a column list ALTERTABLE testpub_tbl8_1 REPLICA IDENTITY FULL; UPDATE testpub_tbl8 SET a = 1;
-- failure: replica identity has to be covered by the column list ALTERTABLE testpub_tbl8_1 DROPCONSTRAINT testpub_tbl8_1_pkey; ALTERTABLE testpub_tbl8_1 ADDPRIMARYKEY (c); ALTERTABLE testpub_tbl8_1 REPLICA IDENTITY USINGINDEX testpub_tbl8_1_pkey; UPDATE testpub_tbl8 SET a = 1;
DROPTABLE testpub_tbl8;
-- column list for partitioned tables has to cover replica identities for -- all child relations CREATETABLE testpub_tbl8 (a int, b text, c text) PARTITION BY HASH (a); ALTER PUBLICATION testpub_col_list ADDTABLE testpub_tbl8 (a, b); -- first partition has replica identity "a" CREATETABLE testpub_tbl8_0 (a int, b text, c text); ALTERTABLE testpub_tbl8_0 ADDPRIMARYKEY (a); ALTERTABLE testpub_tbl8_0 REPLICA IDENTITY USINGINDEX testpub_tbl8_0_pkey; -- second partition has replica identity "b" CREATETABLE testpub_tbl8_1 (a int, b text, c text); ALTERTABLE testpub_tbl8_1 ADDPRIMARYKEY (c); ALTERTABLE testpub_tbl8_1 REPLICA IDENTITY USINGINDEX testpub_tbl8_1_pkey;
-- ok: attaching first partition works, because (a) is in column list ALTERTABLE testpub_tbl8 ATTACH PARTITION testpub_tbl8_0 FORVALUESWITH (modulus 2, remainder 0); -- failure: second partition has replica identity (c), which si not in column list ALTERTABLE testpub_tbl8 ATTACH PARTITION testpub_tbl8_1 FORVALUESWITH (modulus 2, remainder 1); UPDATE testpub_tbl8 SET a = 1;
-- failure: changing replica identity to FULL for partition fails, because -- of the column list on the parent ALTERTABLE testpub_tbl8_0 REPLICA IDENTITY FULL; UPDATE testpub_tbl8 SET a = 1;
-- test that using column list for table is disallowed if any schemas are -- part of the publication SET client_min_messages = 'ERROR'; -- failure - cannot use column list and schema together CREATE PUBLICATION testpub_tbl9 FOR TABLES INSCHEMA public, TABLE public.testpub_tbl7(a); -- ok - only publish schema CREATE PUBLICATION testpub_tbl9 FOR TABLES INSCHEMA public; -- failure - add a table with column list when there is already a schema in the -- publication ALTER PUBLICATION testpub_tbl9 ADDTABLE public.testpub_tbl7(a); -- ok - only publish table with column list ALTER PUBLICATION testpub_tbl9 SETTABLE public.testpub_tbl7(a); -- failure - specify a schema when there is already a column list in the -- publication ALTER PUBLICATION testpub_tbl9 ADD TABLES INSCHEMA public; -- failure - cannot SET column list and schema together ALTER PUBLICATION testpub_tbl9 SET TABLES INSCHEMA public, TABLE public.testpub_tbl7(a); -- ok - drop table ALTER PUBLICATION testpub_tbl9 DROPTABLE public.testpub_tbl7; -- failure - cannot ADD column list and schema together ALTER PUBLICATION testpub_tbl9 ADD TABLES INSCHEMA public, TABLE public.testpub_tbl7(a);
RESET client_min_messages;
-- Test combination of column list and row filter SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_both_filters;
RESET client_min_messages; CREATETABLE testpub_tbl_both_filters (a int, b int, c int, PRIMARYKEY (a,c)); ALTERTABLE testpub_tbl_both_filters REPLICA IDENTITY USINGINDEX testpub_tbl_both_filters_pkey; ALTER PUBLICATION testpub_both_filters ADDTABLE testpub_tbl_both_filters (a,c) WHERE (c != 1);
\dRp+ testpub_both_filters
\d+ testpub_tbl_both_filters
DROPTABLE testpub_tbl_both_filters; DROP PUBLICATION testpub_both_filters; -- ======================================================
-- More column list tests for validating column references CREATETABLE rf_tbl_abcd_nopk(a int, b int, c int, d int); CREATETABLE rf_tbl_abcd_pk(a int, b int, c int, d int, PRIMARYKEY(a,b)); CREATETABLE rf_tbl_abcd_part_pk (a intPRIMARYKEY, b int) PARTITION by RANGE (a); CREATETABLE rf_tbl_abcd_part_pk_1 (b int, a intPRIMARYKEY); ALTERTABLE rf_tbl_abcd_part_pk ATTACH PARTITION rf_tbl_abcd_part_pk_1 FORVALUESFROM (1) TO (10);
-- Case 1. REPLICA IDENTITY DEFAULT (means use primary key or nothing)
-- 1a. REPLICA IDENTITY is DEFAULT and table has a PK. SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub6 FORTABLE rf_tbl_abcd_pk (a, b);
RESET client_min_messages; -- ok - (a,b) covers all PK cols UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (a, b, c); -- ok - (a,b,c) covers all PK cols UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (a); -- fail - "b" is missing from the column list UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (b); -- fail - "a" is missing from the column list UPDATE rf_tbl_abcd_pk SET a = 1;
-- 1b. REPLICA IDENTITY is DEFAULT and table has no PK ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk (a); -- ok - there's no replica identity, so any column list works -- note: it fails anyway, just a bit later because UPDATE requires RI UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Case 2. REPLICA IDENTITY FULL ALTERTABLE rf_tbl_abcd_pk REPLICA IDENTITY FULL; ALTERTABLE rf_tbl_abcd_nopk REPLICA IDENTITY FULL; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (c); -- fail - with REPLICA IDENTITY FULL no column list is allowed UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk (a, b, c, d); -- fail - with REPLICA IDENTITY FULL no column list is allowed UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Case 3. REPLICA IDENTITY NOTHING ALTERTABLE rf_tbl_abcd_pk REPLICA IDENTITY NOTHING; ALTERTABLE rf_tbl_abcd_nopk REPLICA IDENTITY NOTHING; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (a); -- ok - REPLICA IDENTITY NOTHING means all column lists are valid -- it still fails later because without RI we can't replicate updates UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (a, b, c, d); -- ok - REPLICA IDENTITY NOTHING means all column lists are valid -- it still fails later because without RI we can't replicate updates UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk (d); -- ok - REPLICA IDENTITY NOTHING means all column lists are valid -- it still fails later because without RI we can't replicate updates UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Case 4. REPLICA IDENTITY INDEX ALTERTABLE rf_tbl_abcd_pk ALTERCOLUMN c SETNOTNULL; CREATEUNIQUEINDEX idx_abcd_pk_c ON rf_tbl_abcd_pk(c); ALTERTABLE rf_tbl_abcd_pk REPLICA IDENTITY USINGINDEX idx_abcd_pk_c; ALTERTABLE rf_tbl_abcd_nopk ALTERCOLUMN c SETNOTNULL; CREATEUNIQUEINDEX idx_abcd_nopk_c ON rf_tbl_abcd_nopk(c); ALTERTABLE rf_tbl_abcd_nopk REPLICA IDENTITY USINGINDEX idx_abcd_nopk_c; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (a); -- fail - column list "a" does not cover the REPLICA IDENTITY INDEX on "c" UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_pk (c); -- ok - column list "c" does cover the REPLICA IDENTITY INDEX on "c" UPDATE rf_tbl_abcd_pk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk (a); -- fail - column list "a" does not cover the REPLICA IDENTITY INDEX on "c" UPDATE rf_tbl_abcd_nopk SET a = 1; ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_nopk (c); -- ok - column list "c" does cover the REPLICA IDENTITY INDEX on "c" UPDATE rf_tbl_abcd_nopk SET a = 1;
-- Tests for partitioned table
-- set PUBLISH_VIA_PARTITION_ROOT to false and test column list for partitioned -- table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- fail - cannot use column list for partitioned table ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk (a); -- ok - can use column list for partition ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk_1 (a); -- ok - "a" is a PK col UPDATE rf_tbl_abcd_part_pk SET a = 1; -- set PUBLISH_VIA_PARTITION_ROOT to true and test column list for partitioned -- table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=1); -- ok - can use column list for partitioned table ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk (a); -- ok - "a" is a PK col UPDATE rf_tbl_abcd_part_pk SET a = 1; -- fail - cannot set PUBLISH_VIA_PARTITION_ROOT to false if any column list is -- used for partitioned table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- remove partitioned table's column list ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk; -- ok - we don't have column list for partitioned table. ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- Now change the root column list to use a column "b" -- (which is not in the replica identity) ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk_1 (b); -- ok - we don't have column list for partitioned table. ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=0); -- fail - "b" is not in REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_part_pk SET a = 1; -- set PUBLISH_VIA_PARTITION_ROOT to true -- can use column list for partitioned table ALTER PUBLICATION testpub6 SET (PUBLISH_VIA_PARTITION_ROOT=1); -- ok - can use column list for partitioned table ALTER PUBLICATION testpub6 SETTABLE rf_tbl_abcd_part_pk (b); -- fail - "b" is not in REPLICA IDENTITY INDEX UPDATE rf_tbl_abcd_part_pk SET a = 1;
-- Test cache invalidation FOR ALL TABLES publication SET client_min_messages = 'ERROR'; CREATETABLE testpub_tbl4(a int); INSERTINTO testpub_tbl4 values(1); UPDATE testpub_tbl4 set a = 2; CREATE PUBLICATION testpub_foralltables FORALL TABLES;
RESET client_min_messages; -- fail missing REPLICA IDENTITY UPDATE testpub_tbl4 set a = 3; DROP PUBLICATION testpub_foralltables; -- should pass after dropping the publication UPDATE testpub_tbl4 set a = 3; DROPTABLE testpub_tbl4;
-- fail - view ALTER PUBLICATION testpub_default ADDTABLE testpub_view;
ALTER PUBLICATION testpub_default ADDTABLE testpub_tbl1; ALTER PUBLICATION testpub_default SETTABLE testpub_tbl1; ALTER PUBLICATION testpub_default ADDTABLE pub_test.testpub_nopk;
ALTER PUBLICATION testpub_ins_trunct ADDTABLE pub_test.testpub_nopk, testpub_tbl1;
ALTER PUBLICATION testpub_default DROPTABLE testpub_tbl1, pub_test.testpub_nopk; -- fail - nonexistent ALTER PUBLICATION testpub_default DROPTABLE pub_test.testpub_nopk;
\d+ testpub_tbl1
-- verify relation cache invalidation when a primary key is added using -- an existing index CREATETABLE pub_test.testpub_addpk (id intnotnull, data int); ALTER PUBLICATION testpub_default ADDTABLE pub_test.testpub_addpk; INSERTINTO pub_test.testpub_addpk VALUES(1, 11); CREATEUNIQUEINDEX testpub_addpk_id_idx ON pub_test.testpub_addpk(id); -- fail: UPDATE pub_test.testpub_addpk SET id = 2; ALTERTABLE pub_test.testpub_addpk ADDPRIMARYKEYUSINGINDEX testpub_addpk_id_idx; -- now it should work: UPDATE pub_test.testpub_addpk SET id = 2; DROPTABLE pub_test.testpub_addpk;
-- permissions SET ROLE regress_publication_user2; CREATE PUBLICATION testpub2; -- fail
SET ROLE regress_publication_user; GRANTCREATEONDATABASE regression TO regress_publication_user2; SET ROLE regress_publication_user2; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub2; -- ok CREATE PUBLICATION testpub3 FOR TABLES INSCHEMA pub_test; -- fail CREATE PUBLICATION testpub3; -- ok
RESET client_min_messages;
ALTER PUBLICATION testpub2 ADDTABLE testpub_tbl1; -- fail ALTER PUBLICATION testpub3 ADD TABLES INSCHEMA pub_test; -- fail
SET ROLE regress_publication_user; GRANT regress_publication_user TO regress_publication_user2; SET ROLE regress_publication_user2; ALTER PUBLICATION testpub2 ADDTABLE testpub_tbl1; -- ok
DROP PUBLICATION testpub2; DROP PUBLICATION testpub3;
SET ROLE regress_publication_user; CREATE ROLE regress_publication_user3; GRANT regress_publication_user2 TO regress_publication_user3; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub4 FOR TABLES INSCHEMA pub_test;
RESET client_min_messages; ALTER PUBLICATION testpub4 OWNER TO regress_publication_user3; SET ROLE regress_publication_user3; -- fail - new owner must be superuser ALTER PUBLICATION testpub4 owner to regress_publication_user2; -- fail ALTER PUBLICATION testpub4 owner to regress_publication_user; -- ok
SET ROLE regress_publication_user; DROP PUBLICATION testpub4; DROP ROLE regress_publication_user3;
REVOKECREATEONDATABASE regression FROM regress_publication_user2;
DROPTABLE testpub_parted; DROPTABLE testpub_tbl1;
\dRp+ testpub_default
-- fail - must be owner of publication SET ROLE regress_publication_user_dummy; ALTER PUBLICATION testpub_default RENAMETO testpub_dummy;
RESET ROLE;
ALTER PUBLICATION testpub_default RENAMETO testpub_foo;
\dRp testpub_foo
-- rename back to keep the rest simple ALTER PUBLICATION testpub_foo RENAMETO testpub_default;
ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2;
\dRp testpub_default
-- adding schemas and tables CREATESCHEMA pub_test1; CREATESCHEMA pub_test2; CREATESCHEMA pub_test3; CREATESCHEMA"CURRENT_SCHEMA"; CREATETABLE pub_test1.tbl (id int, data text); CREATETABLE pub_test1.tbl1 (id serial primarykey, data text); CREATETABLE pub_test2.tbl1 (id serial primarykey, data text); CREATETABLE"CURRENT_SCHEMA"."CURRENT_SCHEMA"(id int);
-- suppress warning that depends on wal_level SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub1_forschema FOR TABLES INSCHEMA pub_test1;
\dRp+ testpub1_forschema
-- check create publication on CURRENT_SCHEMA where search_path is not set SET SEARCH_PATH=''; CREATE PUBLICATION testpub_forschema FOR TABLES INSCHEMA CURRENT_SCHEMA;
RESET SEARCH_PATH;
-- check create publication on CURRENT_SCHEMA where TABLE/TABLES in SCHEMA -- is not specified CREATE PUBLICATION testpub_forschema1 FOR CURRENT_SCHEMA;
-- check create publication on CURRENT_SCHEMA along with FOR TABLE CREATE PUBLICATION testpub_forschema1 FORTABLE CURRENT_SCHEMA;
-- check create publication on a schema that does not exist CREATE PUBLICATION testpub_forschema FOR TABLES INSCHEMA non_existent_schema;
-- check create publication on a system schema CREATE PUBLICATION testpub_forschema FOR TABLES INSCHEMA pg_catalog;
-- check create publication on an object which is not schema CREATE PUBLICATION testpub1_forschema1 FOR TABLES INSCHEMA testpub_view;
-- dropping the schema should reflect the change in publication DROPSCHEMA pub_test3;
\dRp+ testpub2_forschema
-- renaming the schema should reflect the change in publication ALTERSCHEMA pub_test1 RENAMEto pub_test1_renamed;
\dRp+ testpub2_forschema
-- alter publication add schema ALTER PUBLICATION testpub1_forschema ADD TABLES INSCHEMA pub_test2;
\dRp+ testpub1_forschema
-- add non existent schema ALTER PUBLICATION testpub1_forschema ADD TABLES INSCHEMA non_existent_schema;
\dRp+ testpub1_forschema
-- add a schema which is already added to the publication ALTER PUBLICATION testpub1_forschema ADD TABLES INSCHEMA pub_test1;
\dRp+ testpub1_forschema
-- alter publication drop schema ALTER PUBLICATION testpub1_forschema DROP TABLES INSCHEMA pub_test2;
\dRp+ testpub1_forschema
-- drop schema that is not present in the publication ALTER PUBLICATION testpub1_forschema DROP TABLES INSCHEMA pub_test2;
\dRp+ testpub1_forschema
-- drop a schema that does not exist in the system ALTER PUBLICATION testpub1_forschema DROP TABLES INSCHEMA non_existent_schema;
\dRp+ testpub1_forschema
-- drop all schemas ALTER PUBLICATION testpub1_forschema DROP TABLES INSCHEMA pub_test1;
\dRp+ testpub1_forschema
-- alter publication set multiple schema ALTER PUBLICATION testpub1_forschema SET TABLES INSCHEMA pub_test1, pub_test2;
\dRp+ testpub1_forschema
-- alter publication set non-existent schema ALTER PUBLICATION testpub1_forschema SET TABLES INSCHEMA non_existent_schema;
\dRp+ testpub1_forschema
-- alter publication set it duplicate schemas should set the schemas after -- removing the duplicate schemas ALTER PUBLICATION testpub1_forschema SET TABLES INSCHEMA pub_test1, pub_test1;
\dRp+ testpub1_forschema
-- Verify that it fails to add a schema with a column specification ALTER PUBLICATION testpub1_forschema ADD TABLES INSCHEMA foo (a, b); ALTER PUBLICATION testpub1_forschema ADD TABLES INSCHEMA foo, bar (a, b);
-- cleanup pub_test1 schema for invalidation tests ALTER PUBLICATION testpub2_forschema DROP TABLES INSCHEMA pub_test1; DROP PUBLICATION testpub3_forschema, testpub4_forschema, testpub5_forschema, testpub6_forschema, testpub_fortable; DROPSCHEMA"CURRENT_SCHEMA"CASCADE;
-- verify relation cache invalidations through update statement for the -- default REPLICA IDENTITY on the relation, if schema is part of the -- publication then update will fail because relation's relreplident -- option will be set, if schema is not part of the publication then update -- will be successful. INSERTINTO pub_test1.tbl VALUES(1, 'test');
-- fail UPDATE pub_test1.tbl SET id = 2; ALTER PUBLICATION testpub1_forschema DROP TABLES INSCHEMA pub_test1;
-- success UPDATE pub_test1.tbl SET id = 2; ALTER PUBLICATION testpub1_forschema SET TABLES INSCHEMA pub_test1;
-- fail UPDATE pub_test1.tbl SET id = 2;
-- verify invalidation of partition table having parent and child tables in -- different schema CREATESCHEMA pub_testpart1; CREATESCHEMA pub_testpart2;
CREATETABLE pub_testpart1.parent1 (a int) partition by list (a); CREATETABLE pub_testpart2.child_parent1 partition of pub_testpart1.parent1 forvaluesin (1); INSERTINTO pub_testpart2.child_parent1 values(1); UPDATE pub_testpart2.child_parent1 set a = 1; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpubpart_forschema FOR TABLES INSCHEMA pub_testpart1;
RESET client_min_messages;
-- fail UPDATE pub_testpart1.parent1 set a = 1; UPDATE pub_testpart2.child_parent1 set a = 1;
DROP PUBLICATION testpubpart_forschema;
-- verify invalidation of partition tables for schema publication that has -- parent and child tables of different partition hierarchies CREATETABLE pub_testpart2.parent2 (a int) partition by list (a); CREATETABLE pub_testpart1.child_parent2 partition of pub_testpart2.parent2 forvaluesin (1); INSERTINTO pub_testpart1.child_parent2 values(1); UPDATE pub_testpart1.child_parent2 set a = 1; SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpubpart_forschema FOR TABLES INSCHEMA pub_testpart2;
RESET client_min_messages;
-- fail UPDATE pub_testpart2.child_parent1 set a = 1; UPDATE pub_testpart2.parent2 set a = 1; UPDATE pub_testpart1.child_parent2 set a = 1;
-- alter publication set 'TABLES IN SCHEMA' on an empty publication. SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub3_forschema;
RESET client_min_messages;
\dRp+ testpub3_forschema ALTER PUBLICATION testpub3_forschema SET TABLES INSCHEMA pub_test1;
\dRp+ testpub3_forschema
-- create publication including both 'FOR TABLE' and 'FOR TABLES IN SCHEMA' SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_forschema_fortable FOR TABLES INSCHEMA pub_test1, TABLE pub_test2.tbl1; CREATE PUBLICATION testpub_fortable_forschema FORTABLE pub_test2.tbl1, TABLES INSCHEMApub_test1;
RESET client_min_messages;
-- fail specifying table without any of 'FOR TABLES IN SCHEMA' or --'FOR TABLE' or 'FOR ALL TABLES' CREATE PUBLICATION testpub_error FOR pub_test2.tbl1;
DROP VIEW testpub_view;
DROP PUBLICATION testpub_default; DROP PUBLICATION testpub_ins_trunct; DROP PUBLICATION testpub_fortbl; DROP PUBLICATION testpub1_forschema; DROP PUBLICATION testpub2_forschema; DROP PUBLICATION testpub3_forschema; DROP PUBLICATION testpub_forschema_fortable; DROP PUBLICATION testpub_fortable_forschema; DROP PUBLICATION testpubpart_forschema;
-- Test the list of partitions published with or without -- 'PUBLISH_VIA_PARTITION_ROOT' parameter SET client_min_messages = 'ERROR'; CREATESCHEMA sch1; CREATESCHEMA sch2; CREATETABLE sch1.tbl1 (a int) PARTITION BY RANGE(a); CREATETABLE sch2.tbl1_part1 PARTITION OF sch1.tbl1 FORVALUESFROM (1) to (10); -- Schema publication that does not include the schema that has the parent table CREATE PUBLICATION pub FOR TABLES INSCHEMA sch2 WITH (PUBLISH_VIA_PARTITION_ROOT=1); SELECT * FROM pg_publication_tables;
DROP PUBLICATION pub; -- Table publication that does not include the parent table CREATE PUBLICATION pub FORTABLE sch2.tbl1_part1 WITH (PUBLISH_VIA_PARTITION_ROOT=1); SELECT * FROM pg_publication_tables;
-- Table publication that includes both the parent table and the child table ALTER PUBLICATION pub ADDTABLE sch1.tbl1; SELECT * FROM pg_publication_tables;
DROP PUBLICATION pub; -- Schema publication that does not include the schema that has the parent table CREATE PUBLICATION pub FOR TABLES INSCHEMA sch2 WITH (PUBLISH_VIA_PARTITION_ROOT=0); SELECT * FROM pg_publication_tables;
DROP PUBLICATION pub; -- Table publication that does not include the parent table CREATE PUBLICATION pub FORTABLE sch2.tbl1_part1 WITH (PUBLISH_VIA_PARTITION_ROOT=0); SELECT * FROM pg_publication_tables;
-- Table publication that includes both the parent table and the child table ALTER PUBLICATION pub ADDTABLE sch1.tbl1; SELECT * FROM pg_publication_tables;
DROP PUBLICATION pub; DROPTABLE sch2.tbl1_part1; DROPTABLE sch1.tbl1;
CREATETABLE sch1.tbl1 (a int) PARTITION BY RANGE(a); CREATETABLE sch1.tbl1_part1 PARTITION OF sch1.tbl1 FORVALUESFROM (1) to (10); CREATETABLE sch1.tbl1_part2 PARTITION OF sch1.tbl1 FORVALUESFROM (10) to (20); CREATETABLE sch1.tbl1_part3 (a int) PARTITION BY RANGE(a); ALTERTABLE sch1.tbl1 ATTACH PARTITION sch1.tbl1_part3 FORVALUESFROM (20) to (30); CREATE PUBLICATION pub FOR TABLES INSCHEMA sch1 WITH (PUBLISH_VIA_PARTITION_ROOT=1); SELECT * FROM pg_publication_tables;
-- Test the 'publish_generated_columns' parameter with the following values: -- 'stored', 'none'. SET client_min_messages = 'ERROR'; CREATE PUBLICATION pub1 FORALL TABLES WITH (publish_generated_columns = stored);
\dRp+ pub1 CREATE PUBLICATION pub2 FORALL TABLES WITH (publish_generated_columns = none);
\dRp+ pub2
DROP PUBLICATION pub1; DROP PUBLICATION pub2;
-- Test the 'publish_generated_columns' parameter as 'none' and 'stored' for -- different scenarios with/without generated columns in column lists. CREATETABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
-- Generated columns in column list, when 'publish_generated_columns'='none' CREATE PUBLICATION pub1 FORtable gencols(a, gen1) WITH (publish_generated_columns = none);
\dRp+ pub1
-- Generated columns in column list, when 'publish_generated_columns'='stored' CREATE PUBLICATION pub2 FORtable gencols(a, gen1) WITH (publish_generated_columns = stored);
\dRp+ pub2
-- Generated columns in column list, then set 'publish_generated_columns'='none' ALTER PUBLICATION pub2 SET (publish_generated_columns = none);
\dRp+ pub2
-- Remove generated columns from column list, when 'publish_generated_columns'='none' ALTER PUBLICATION pub2 SETTABLE gencols(a);
\dRp+ pub2
-- Add generated columns in column list, when 'publish_generated_columns'='none' ALTER PUBLICATION pub2 SETTABLE gencols(a, gen1);
\dRp+ pub2
DROP PUBLICATION pub1; DROP PUBLICATION pub2; DROPTABLE gencols;
RESET client_min_messages;
-- Test that the INSERT ON CONFLICT command correctly checks REPLICA IDENTITY -- when the target table is published. CREATETABLE testpub_insert_onconfl_no_ri (a intunique, b int); CREATETABLE testpub_insert_onconfl_parted (a intunique, b int) PARTITION by RANGE (a); CREATETABLE testpub_insert_onconfl_part_no_ri PARTITION OF testpub_insert_onconfl_parted FORVALUESFROM (1) TO (10);
-- fail - missing REPLICA IDENTITY INSERTINTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT (a) DO UPDATESET b = 2;
-- ok - no updates INSERTINTO testpub_insert_onconfl_no_ri VALUES (1, 1) ON CONFLICT DO NOTHING;
-- fail - missing REPLICA IDENTITY in partition testpub_insert_onconfl_no_ri INSERTINTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT (a) DO UPDATESET b = 2;
-- ok - no updates INSERTINTO testpub_insert_onconfl_parted VALUES (1, 1) ON CONFLICT DO NOTHING;
DROP PUBLICATION pub1; DROPTABLE testpub_insert_onconfl_no_ri; DROPTABLE testpub_insert_onconfl_parted;
-- Test that the MERGE command correctly checks REPLICA IDENTITY when the -- target table is published. CREATETABLE testpub_merge_no_ri (a int, b int); CREATETABLE testpub_merge_pk (a intprimarykey, b int);
-- fail - missing REPLICA IDENTITY
MERGE INTO testpub_merge_no_ri USING testpub_merge_pk s ON s.a >= 1 WHEN MATCHED THENUPDATESET b = s.b;
-- fail - missing REPLICA IDENTITY
MERGE INTO testpub_merge_no_ri USING testpub_merge_pk s ON s.a >= 1 WHEN MATCHED THENDELETE;
-- ok - insert and do nothing are not restricted
MERGE INTO testpub_merge_no_ri USING testpub_merge_pk s ON s.a >= 1 WHEN MATCHED THEN DO NOTHING WHENNOT MATCHED THENINSERT (a, b) VALUES (0, 0);
-- ok - REPLICA IDENTITY is DEFAULT and table has a PK
MERGE INTO testpub_merge_pk USING testpub_merge_no_ri s ON s.a >= 1 WHEN MATCHED AND s.a > 0THENUPDATESET b = s.b WHEN MATCHED THENDELETE;
DROP PUBLICATION pub1; DROPTABLE testpub_merge_no_ri; DROPTABLE testpub_merge_pk;
RESET SESSION AUTHORIZATION; DROP ROLE regress_publication_user, regress_publication_user2; DROP ROLE regress_publication_user_dummy;
-- stage objects for pg_dump tests CREATESCHEMA pubme CREATETABLE t0 (c int, d int) CREATETABLE t1 (c int); CREATESCHEMA pubme2 CREATETABLE t0 (c int, d int); SET client_min_messages = 'ERROR'; CREATE PUBLICATION dump_pub_qual_1ct FOR TABLE ONLY pubme.t0 (c, d) WHERE (c > 0); CREATE PUBLICATION dump_pub_qual_2ct FOR TABLE ONLY pubme.t0 (c) WHERE (c > 0), TABLE ONLY pubme.t1 (c); CREATE PUBLICATION dump_pub_nsp_1ct FOR
TABLES INSCHEMA pubme; CREATE PUBLICATION dump_pub_nsp_2ct FOR
TABLES INSCHEMA pubme,
TABLES INSCHEMA pubme2; CREATE PUBLICATION dump_pub_all FOR TABLE ONLY pubme.t0, TABLE ONLY pubme.t1 WHERE (c < 0),
TABLES INSCHEMA pubme,
TABLES INSCHEMA pubme2 WITH (publish_via_partition_root = true);
RESET client_min_messages;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.