diff --git a/src/test/regress/expected/propagate_extension_commands.out b/src/test/regress/expected/propagate_extension_commands.out index 36f7254c9..969a52b97 100644 --- a/src/test/regress/expected/propagate_extension_commands.out +++ b/src/test/regress/expected/propagate_extension_commands.out @@ -226,16 +226,17 @@ $$); (1 row) CREATE EXTENSION dict_int FROM unpackaged; +ERROR: CREATE EXTENSION ... FROM is no longer supported SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHERE extname = 'dict_int'$$); run_command_on_workers --------------------------------------------------------------------- - (localhost,57637,t,1) + (localhost,57637,t,0) (1 row) SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'dict_int'$$); run_command_on_workers --------------------------------------------------------------------- - (localhost,57637,t,1.0) + (localhost,57637,t,"") (1 row) -- and add the other node @@ -264,15 +265,15 @@ SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extnam SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHERE extname = 'dict_int'$$); run_command_on_workers --------------------------------------------------------------------- - (localhost,57637,t,1) - (localhost,57638,t,1) + (localhost,57637,t,0) + (localhost,57638,t,0) (2 rows) SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'dict_int'$$); run_command_on_workers --------------------------------------------------------------------- - (localhost,57637,t,1.0) - (localhost,57638,t,1.0) + (localhost,57637,t,"") + (localhost,57638,t,"") (2 rows) -- and similarly check for the reference table diff --git a/src/test/regress/expected/propagate_extension_commands_1.out b/src/test/regress/expected/propagate_extension_commands_1.out new file mode 100644 index 000000000..36f7254c9 --- /dev/null +++ b/src/test/regress/expected/propagate_extension_commands_1.out @@ -0,0 +1,444 @@ +CREATE SCHEMA "extension'test"; +-- use a schema name with escape character +SET search_path TO "extension'test"; +SET client_min_messages TO WARNING; +-- create an extension on the given search_path +-- the extension is on contrib, so should be avaliable for the regression tests +CREATE EXTENSION seg; +-- make sure that both the schema and the extension is distributed +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_extension WHERE extname = 'seg'); + count +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_namespace WHERE nspname = 'extension''test'); + count +--------------------------------------------------------------------- + 1 +(1 row) + +CREATE TABLE test_table (key int, value seg); +SELECT create_distributed_table('test_table', 'key'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- make sure that the table is also distributed now +SELECT count(*) from pg_dist_partition where logicalrelid='extension''test.test_table'::regclass; + count +--------------------------------------------------------------------- + 1 +(1 row) + +CREATE TYPE two_segs AS (seg_1 seg, seg_2 seg); +-- verify that the type that depends on the extension is also marked as distributed +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_type WHERE typname = 'two_segs' AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'extension''test')); + count +--------------------------------------------------------------------- + 1 +(1 row) + +-- now try to run CREATE EXTENSION within a transction block, all should work fine +BEGIN; + CREATE EXTENSION isn WITH SCHEMA public; + -- now, try create a reference table relying on the data types + -- this should not succeed as we do not distribute extension commands within transaction blocks + CREATE TABLE dist_table (key int, value public.issn); + SELECT create_distributed_table('dist_table', 'key'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + + -- we can even run queries (sequentially) over the distributed table + SELECT * FROM dist_table; + key | value +--------------------------------------------------------------------- +(0 rows) + + INSERT INTO dist_table VALUES (1, public.issn('1436-4522')); + INSERT INTO dist_table SELECT * FROM dist_table RETURNING *; + key | value +--------------------------------------------------------------------- + 1 | 1436-4522 +(1 row) + +COMMIT; +-- make sure that the extension is distributed even if we run create extension in a transaction block +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_extension WHERE extname = 'isn'); + count +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT run_command_on_workers($$SELECT count(*) FROM pg_extension WHERE extname = 'isn'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1) + (localhost,57638,t,1) +(2 rows) + +CREATE TABLE ref_table (a public.issn); +-- now, create a reference table relying on the data types +SELECT create_reference_table('ref_table'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +-- now, drop the extension, recreate it with an older version and update it to latest version +DROP EXTENSION isn CASCADE; +CREATE EXTENSION isn WITH VERSION "1.1"; +-- before updating the version, ensure the current version +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'isn'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.1) + (localhost,57638,t,1.1) +(2 rows) + +-- now, update to a newer version +ALTER EXTENSION isn UPDATE TO '1.2'; +-- show that ALTER EXTENSION is propagated +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'isn'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.2) + (localhost,57638,t,1.2) +(2 rows) + +-- before changing the schema, ensure the current schmea +SELECT run_command_on_workers($$SELECT nspname from pg_namespace where oid=(SELECT extnamespace FROM pg_extension WHERE extname = 'isn')$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,extension'test) + (localhost,57638,t,extension'test) +(2 rows) + +-- now change the schema +ALTER EXTENSION isn SET SCHEMA public; +-- switch back to public schema as we set extension's schema to public +SET search_path TO public; +-- make sure that the extension is distributed +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_extension WHERE extname = 'isn'); + count +--------------------------------------------------------------------- + 1 +(1 row) + +-- show that the ALTER EXTENSION command is propagated +SELECT run_command_on_workers($$SELECT nspname from pg_namespace where oid=(SELECT extnamespace FROM pg_extension WHERE extname = 'isn')$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,public) + (localhost,57638,t,public) +(2 rows) + +-- drop the extension finally +DROP EXTENSION isn CASCADE; +-- now make sure that the reference tables depending on an extension can be succesfully created. +-- we should also ensure that we replicate this reference table (and hence the extension) +-- to new nodes after calling master_activate_node. +-- now, first drop seg and existing objects before next test +DROP EXTENSION seg CASCADE; +-- but as we have only 2 ports in postgresql tests, let's remove one of the nodes first +-- before remove, first remove the existing relations (due to the other tests) +DROP SCHEMA "extension'test" CASCADE; +SELECT 1 from master_remove_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +-- then create the extension +CREATE EXTENSION seg; +-- show that the extension is created on existing worker +SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHERE extname = 'seg'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1) +(1 row) + +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.3) +(1 row) + +-- now create the reference table +CREATE TABLE ref_table_2 (x seg); +SELECT create_reference_table('ref_table_2'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +-- we also add an old style extension from before extensions which we upgrade to an extension +-- by exercising it before the add node we verify it will create the extension (without upgrading) +-- it on the new worker as well. For this we use the dict_int extension which is in contrib, +-- supports FROM unpackaged, and is relatively small +-- create objects for dict_int manually so we can upgrade from unpacked +CREATE FUNCTION dintdict_init(internal) RETURNS internal AS 'dict_int.so' LANGUAGE C STRICT; +CREATE FUNCTION dintdict_lexize(internal, internal, internal, internal) RETURNS internal AS 'dict_int.so' LANGUAGE C STRICT; +CREATE TEXT SEARCH TEMPLATE intdict_template (LEXIZE = dintdict_lexize, INIT = dintdict_init ); +CREATE TEXT SEARCH DICTIONARY intdict (TEMPLATE = intdict_template); +COMMENT ON TEXT SEARCH DICTIONARY intdict IS 'dictionary for integers'; +SELECT run_command_on_workers($$ +CREATE FUNCTION dintdict_init(internal) RETURNS internal AS 'dict_int.so' LANGUAGE C STRICT; +$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,"CREATE FUNCTION") +(1 row) + +SELECT run_command_on_workers($$ +CREATE FUNCTION dintdict_lexize(internal, internal, internal, internal) RETURNS internal AS 'dict_int.so' LANGUAGE C STRICT; +$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,"CREATE FUNCTION") +(1 row) + +SELECT run_command_on_workers($$ +CREATE TEXT SEARCH TEMPLATE intdict_template (LEXIZE = dintdict_lexize, INIT = dintdict_init ); +$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,"CREATE TEXT SEARCH TEMPLATE") +(1 row) + +SELECT run_command_on_workers($$ +CREATE TEXT SEARCH DICTIONARY intdict (TEMPLATE = intdict_template); +$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,"CREATE TEXT SEARCH DICTIONARY") +(1 row) + +SELECT run_command_on_workers($$ +COMMENT ON TEXT SEARCH DICTIONARY intdict IS 'dictionary for integers'; +$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,COMMENT) +(1 row) + +CREATE EXTENSION dict_int FROM unpackaged; +SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHERE extname = 'dict_int'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1) +(1 row) + +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'dict_int'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.0) +(1 row) + +-- and add the other node +SELECT 1 from master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +-- show that the extension is created on both existing and new node +SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHERE extname = 'seg'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1) + (localhost,57638,t,1) +(2 rows) + +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.3) + (localhost,57638,t,1.3) +(2 rows) + +-- check for the unpackaged extension to be created correctly +SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHERE extname = 'dict_int'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1) + (localhost,57638,t,1) +(2 rows) + +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'dict_int'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.0) + (localhost,57638,t,1.0) +(2 rows) + +-- and similarly check for the reference table +select count(*) from pg_dist_partition where partmethod='n' and logicalrelid='ref_table_2'::regclass; + count +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT count(*) FROM pg_dist_shard WHERE logicalrelid='ref_table_2'::regclass; + count +--------------------------------------------------------------------- + 1 +(1 row) + +DROP TABLE ref_table_2; +-- now test create extension in another transaction block but rollback this time +BEGIN; + CREATE EXTENSION isn WITH VERSION '1.1' SCHEMA public; +ROLLBACK; +-- at the end of the transaction block, we did not create isn extension in coordinator or worker nodes as we rollback'ed +-- make sure that the extension is not distributed +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_extension WHERE extname = 'isn'); + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- and the extension does not exist on workers +SELECT run_command_on_workers($$SELECT count(*) FROM pg_extension WHERE extname = 'isn'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,0) + (localhost,57638,t,0) +(2 rows) + +-- give a notice for the following commands saying that it is not +-- propagated to the workers. the user should run it manually on the workers +CREATE TABLE t1 (A int); +CREATE VIEW v1 AS select * from t1; +ALTER EXTENSION seg ADD VIEW v1; +ALTER EXTENSION seg DROP VIEW v1; +DROP VIEW v1; +DROP TABLE t1; +-- drop multiple extensions at the same time +CREATE EXTENSION isn WITH VERSION '1.1' SCHEMA public; +-- let's create another extension locally +set citus.enable_ddl_propagation to 'off'; +CREATE EXTENSION pg_buffercache; +set citus.enable_ddl_propagation to 'on'; +DROP EXTENSION pg_buffercache, isn CASCADE; +SELECT count(*) FROM pg_extension WHERE extname IN ('pg_buffercache', 'isn'); + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- drop extension should just work +DROP EXTENSION seg CASCADE; +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_extension WHERE extname = 'seg'); + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT run_command_on_workers($$SELECT count(*) FROM pg_extension WHERE extname = 'seg'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,0) + (localhost,57638,t,0) +(2 rows) + +-- make sure that the extension is not avaliable anymore as a distributed object +SELECT count(*) FROM citus.pg_dist_object WHERE objid = (SELECT oid FROM pg_extension WHERE extname IN ('seg', 'isn')); + count +--------------------------------------------------------------------- + 0 +(1 row) + +CREATE SCHEMA "extension'test"; +SET search_path TO "extension'test"; +-- check restriction for sequential execution +-- enable it and see that create command errors but continues its execution by changing citus.multi_shard_modify_mode TO 'off +BEGIN; + CREATE TABLE some_random_table (a int); + SELECT create_distributed_table('some_random_table', 'a'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + + CREATE EXTENSION seg; + CREATE TABLE some_random_table_2 (a int, b seg); + SELECT create_distributed_table('some_random_table_2', 'a'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +ROLLBACK; +-- show that the CREATE EXTENSION command propagated even if the transaction +-- block is rollbacked, that's a shortcoming of dependency creation logic +SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,1.3) + (localhost,57638,t,1.3) +(2 rows) + +-- drop the schema and all the objects +DROP SCHEMA "extension'test" CASCADE; +-- recreate for the next tests +CREATE SCHEMA "extension'test"; +-- use a schema name with escape character +SET search_path TO "extension'test"; +-- remove the node, we'll add back again +SELECT 1 from master_remove_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +-- now, create a type that depends on another type, which +-- finally depends on an extension +BEGIN; + SET citus.shard_replication_factor TO 1; + CREATE EXTENSION seg; + CREATE EXTENSION isn; + CREATE TYPE test_type AS (a int, b seg); + CREATE TYPE test_type_2 AS (a int, b test_type); + CREATE TABLE t2 (a int, b test_type_2, c issn); + SELECT create_distributed_table('t2', 'a'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + + CREATE TYPE test_type_3 AS (a int, b test_type, c issn); + CREATE TABLE t3 (a int, b test_type_3); + SELECT create_reference_table('t3'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +COMMIT; +-- add the node back +SELECT 1 from master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +-- make sure that both extensions are created on both nodes +SELECT count(*) FROM citus.pg_dist_object WHERE objid IN (SELECT oid FROM pg_extension WHERE extname IN ('seg', 'isn')); + count +--------------------------------------------------------------------- + 2 +(1 row) + +SELECT run_command_on_workers($$SELECT count(*) FROM pg_extension WHERE extname IN ('seg', 'isn')$$); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,2) + (localhost,57638,t,2) +(2 rows) + +-- drop the schema and all the objects +DROP SCHEMA "extension'test" CASCADE;