From 22df8027b03e4d4afb0b8352567eb9fedb5762e2 Mon Sep 17 00:00:00 2001 From: Nils Dijk Date: Tue, 17 Nov 2020 18:44:37 +0100 Subject: [PATCH] add extra output for multi_extension targeting pg11 --- src/test/regress/expected/multi_extension.out | 10 + .../regress/expected/multi_extension_0.out | 829 ++++++++++++++++++ src/test/regress/sql/multi_extension.sql | 5 + 3 files changed, 844 insertions(+) create mode 100644 src/test/regress/expected/multi_extension_0.out diff --git a/src/test/regress/expected/multi_extension.out b/src/test/regress/expected/multi_extension.out index 7ec7ad649..08f92c034 100644 --- a/src/test/regress/expected/multi_extension.out +++ b/src/test/regress/expected/multi_extension.out @@ -5,6 +5,16 @@ -- -- It'd be nice to script generation of this file, but alas, that's -- not done yet. +-- differentiate the output file for pg11 and versions above, with regards to objects +-- created per citus version depending on the postgres version. Upgrade tests verify the +-- objects are added in citus_finish_pg_upgrade() +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 11 AS version_above_eleven; + version_above_eleven +--------------------------------------------------------------------- + t +(1 row) + SET citus.next_shard_id TO 580000; SELECT $definition$ CREATE OR REPLACE FUNCTION test.maintenance_worker() diff --git a/src/test/regress/expected/multi_extension_0.out b/src/test/regress/expected/multi_extension_0.out new file mode 100644 index 000000000..9605e9d32 --- /dev/null +++ b/src/test/regress/expected/multi_extension_0.out @@ -0,0 +1,829 @@ +-- +-- MULTI_EXTENSION +-- +-- Tests around extension creation / upgrades +-- +-- It'd be nice to script generation of this file, but alas, that's +-- not done yet. +-- differentiate the output file for pg11 and versions above, with regards to objects +-- created per citus version depending on the postgres version. Upgrade tests verify the +-- objects are added in citus_finish_pg_upgrade() +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 11 AS version_above_eleven; + version_above_eleven +--------------------------------------------------------------------- + f +(1 row) + +SET citus.next_shard_id TO 580000; +SELECT $definition$ +CREATE OR REPLACE FUNCTION test.maintenance_worker() + RETURNS pg_stat_activity + LANGUAGE plpgsql +AS $$ +DECLARE + activity record; +BEGIN + DO 'BEGIN END'; -- Force maintenance daemon to start + -- we don't want to wait forever; loop will exit after 20 seconds + FOR i IN 1 .. 200 LOOP + PERFORM pg_stat_clear_snapshot(); + SELECT * INTO activity FROM pg_stat_activity + WHERE application_name = 'Citus Maintenance Daemon' AND datname = current_database(); + IF activity.pid IS NOT NULL THEN + RETURN activity; + ELSE + PERFORM pg_sleep(0.1); + END IF ; + END LOOP; + -- fail if we reach the end of this loop + raise 'Waited too long for maintenance daemon to start'; +END; +$$; +$definition$ create_function_test_maintenance_worker +\gset +CREATE TABLE prev_objects(description text); +CREATE TABLE extension_diff(previous_object text COLLATE "C", + current_object text COLLATE "C"); +CREATE FUNCTION print_extension_changes() +RETURNS TABLE(previous_object text, current_object text) +AS $func$ +BEGIN + TRUNCATE TABLE extension_diff; + + CREATE TABLE current_objects AS + SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS description + FROM pg_catalog.pg_depend, pg_catalog.pg_extension e + WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass + AND refobjid = e.oid + AND deptype = 'e' + AND e.extname='citus'; + + INSERT INTO extension_diff + SELECT p.description previous_object, c.description current_object + FROM current_objects c FULL JOIN prev_objects p + ON p.description = c.description + WHERE p.description is null OR c.description is null; + + DROP TABLE prev_objects; + ALTER TABLE current_objects RENAME TO prev_objects; + + RETURN QUERY SELECT * FROM extension_diff ORDER BY 1, 2; +END +$func$ LANGUAGE plpgsql; +CREATE SCHEMA test; +:create_function_test_maintenance_worker +-- check maintenance daemon is started +SELECT datname, current_database(), + usename, (SELECT extowner::regrole::text FROM pg_extension WHERE extname = 'citus') +FROM test.maintenance_worker(); + datname | current_database | usename | extowner +--------------------------------------------------------------------- + regression | regression | postgres | postgres +(1 row) + +-- ensure no objects were created outside pg_catalog +SELECT COUNT(*) +FROM pg_depend AS pgd, + pg_extension AS pge, + LATERAL pg_identify_object(pgd.classid, pgd.objid, pgd.objsubid) AS pgio +WHERE pgd.refclassid = 'pg_extension'::regclass AND + pgd.refobjid = pge.oid AND + pge.extname = 'citus' AND + pgio.schema NOT IN ('pg_catalog', 'citus', 'citus_internal', 'test', 'cstore'); + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- DROP EXTENSION pre-created by the regression suite +DROP EXTENSION citus; +\c +-- these tests switch between citus versions and call ddl's that require pg_dist_object to be created +SET citus.enable_object_propagation TO 'false'; +SET citus.enable_version_checks TO 'false'; +CREATE EXTENSION citus VERSION '7.0-1'; +ALTER EXTENSION citus UPDATE TO '7.0-2'; +ALTER EXTENSION citus UPDATE TO '7.0-3'; +ALTER EXTENSION citus UPDATE TO '7.0-4'; +ALTER EXTENSION citus UPDATE TO '7.0-5'; +ALTER EXTENSION citus UPDATE TO '7.0-6'; +ALTER EXTENSION citus UPDATE TO '7.0-7'; +ALTER EXTENSION citus UPDATE TO '7.0-8'; +ALTER EXTENSION citus UPDATE TO '7.0-9'; +ALTER EXTENSION citus UPDATE TO '7.0-10'; +ALTER EXTENSION citus UPDATE TO '7.0-11'; +ALTER EXTENSION citus UPDATE TO '7.0-12'; +ALTER EXTENSION citus UPDATE TO '7.0-13'; +ALTER EXTENSION citus UPDATE TO '7.0-14'; +ALTER EXTENSION citus UPDATE TO '7.0-15'; +ALTER EXTENSION citus UPDATE TO '7.1-1'; +ALTER EXTENSION citus UPDATE TO '7.1-2'; +ALTER EXTENSION citus UPDATE TO '7.1-3'; +ALTER EXTENSION citus UPDATE TO '7.1-4'; +ALTER EXTENSION citus UPDATE TO '7.2-1'; +ALTER EXTENSION citus UPDATE TO '7.2-2'; +ALTER EXTENSION citus UPDATE TO '7.2-3'; +ALTER EXTENSION citus UPDATE TO '7.3-3'; +ALTER EXTENSION citus UPDATE TO '7.4-1'; +ALTER EXTENSION citus UPDATE TO '7.4-2'; +ALTER EXTENSION citus UPDATE TO '7.4-3'; +ALTER EXTENSION citus UPDATE TO '7.5-1'; +ALTER EXTENSION citus UPDATE TO '7.5-2'; +ALTER EXTENSION citus UPDATE TO '7.5-3'; +ALTER EXTENSION citus UPDATE TO '7.5-4'; +ALTER EXTENSION citus UPDATE TO '7.5-5'; +ALTER EXTENSION citus UPDATE TO '7.5-6'; +ALTER EXTENSION citus UPDATE TO '7.5-7'; +ALTER EXTENSION citus UPDATE TO '8.0-1'; +ALTER EXTENSION citus UPDATE TO '8.0-2'; +ALTER EXTENSION citus UPDATE TO '8.0-3'; +ALTER EXTENSION citus UPDATE TO '8.0-4'; +ALTER EXTENSION citus UPDATE TO '8.0-5'; +ALTER EXTENSION citus UPDATE TO '8.0-6'; +ALTER EXTENSION citus UPDATE TO '8.0-7'; +ALTER EXTENSION citus UPDATE TO '8.0-8'; +ALTER EXTENSION citus UPDATE TO '8.0-9'; +ALTER EXTENSION citus UPDATE TO '8.0-10'; +ALTER EXTENSION citus UPDATE TO '8.0-11'; +ALTER EXTENSION citus UPDATE TO '8.0-12'; +ALTER EXTENSION citus UPDATE TO '8.0-13'; +ALTER EXTENSION citus UPDATE TO '8.1-1'; +ALTER EXTENSION citus UPDATE TO '8.2-1'; +ALTER EXTENSION citus UPDATE TO '8.2-2'; +ALTER EXTENSION citus UPDATE TO '8.2-3'; +ALTER EXTENSION citus UPDATE TO '8.2-4'; +ALTER EXTENSION citus UPDATE TO '8.3-1'; +ALTER EXTENSION citus UPDATE TO '9.0-1'; +ALTER EXTENSION citus UPDATE TO '9.0-2'; +ALTER EXTENSION citus UPDATE TO '9.1-1'; +ALTER EXTENSION citus UPDATE TO '9.2-1'; +ALTER EXTENSION citus UPDATE TO '9.2-2'; +-- Snapshot of state at 9.2-2 +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- + | event trigger citus_cascade_to_partition + | function alter_role_if_exists(text,text) + | function any_value(anyelement) + | function any_value_agg(anyelement,anyelement) + | function array_cat_agg(anyarray) + | function assign_distributed_transaction_id(integer,bigint,timestamp with time zone) + | function authinfo_valid(text) + | function broadcast_intermediate_result(text,text) + | function check_distributed_deadlocks() + | function citus_add_rebalance_strategy(name,regproc,regproc,regproc,real,real) + | function citus_blocking_pids(integer) + | function citus_create_restore_point(text) + | function citus_dist_stat_activity() + | function citus_drop_trigger() + | function citus_executor_name(integer) + | function citus_extradata_container(internal) + | function citus_finish_pg_upgrade() + | function citus_internal.find_groupid_for_node(text,integer) + | function citus_internal.pg_dist_node_trigger_func() + | function citus_internal.pg_dist_rebalance_strategy_enterprise_check() + | function citus_internal.pg_dist_rebalance_strategy_trigger_func() + | function citus_internal.pg_dist_shard_placement_trigger_func() + | function citus_internal.refresh_isolation_tester_prepared_statement() + | function citus_internal.replace_isolation_tester_func() + | function citus_internal.restore_isolation_tester_func() + | function citus_isolation_test_session_is_blocked(integer,integer[]) + | function citus_json_concatenate(json,json) + | function citus_json_concatenate_final(json) + | function citus_jsonb_concatenate(jsonb,jsonb) + | function citus_jsonb_concatenate_final(jsonb) + | function citus_node_capacity_1(integer) + | function citus_prepare_pg_upgrade() + | function citus_query_stats() + | function citus_relation_size(regclass) + | function citus_server_id() + | function citus_set_default_rebalance_strategy(text) + | function citus_shard_allowed_on_node_true(bigint,integer) + | function citus_shard_cost_1(bigint) + | function citus_shard_cost_by_disk_size(bigint) + | function citus_stat_statements() + | function citus_stat_statements_reset() + | function citus_table_is_visible(oid) + | function citus_table_size(regclass) + | function citus_text_send_as_jsonb(text) + | function citus_total_relation_size(regclass) + | function citus_truncate_trigger() + | function citus_validate_rebalance_strategy_functions(regproc,regproc,regproc) + | function citus_version() + | function citus_worker_stat_activity() + | function column_name_to_column(regclass,text) + | function column_to_column_name(regclass,text) + | function coord_combine_agg(oid,cstring,anyelement) + | function coord_combine_agg_ffunc(internal,oid,cstring,anyelement) + | function coord_combine_agg_sfunc(internal,oid,cstring,anyelement) + | function create_distributed_function(regprocedure,text,text) + | function create_distributed_table(regclass,text,citus.distribution_type,text) + | function create_intermediate_result(text,text) + | function create_reference_table(regclass) + | function distributed_tables_colocated(regclass,regclass) + | function dump_global_wait_edges() + | function dump_local_wait_edges() + | function fetch_intermediate_results(text[],text,integer) + | function get_all_active_transactions() + | function get_colocated_shard_array(bigint) + | function get_colocated_table_array(regclass) + | function get_current_transaction_id() + | function get_global_active_transactions() + | function get_rebalance_progress() + | function get_rebalance_table_shards_plan(regclass,real,integer,bigint[],boolean,name) + | function get_shard_id_for_distribution_column(regclass,"any") + | function isolate_tenant_to_new_shard(regclass,"any",text) + | function json_cat_agg(json) + | function jsonb_cat_agg(jsonb) + | function lock_relation_if_exists(text,text) + | function lock_shard_metadata(integer,bigint[]) + | function lock_shard_resources(integer,bigint[]) + | function mark_tables_colocated(regclass,regclass[]) + | function master_activate_node(text,integer) + | function master_add_inactive_node(text,integer,integer,noderole,name) + | function master_add_node(text,integer,integer,noderole,name) + | function master_add_secondary_node(text,integer,text,integer,name) + | function master_append_table_to_shard(bigint,text,text,integer) + | function master_apply_delete_command(text) + | function master_conninfo_cache_invalidate() + | function master_copy_shard_placement(bigint,text,integer,text,integer,boolean,citus.shard_transfer_mode) + | function master_create_distributed_table(regclass,text,citus.distribution_type) + | function master_create_empty_shard(text) + | function master_create_worker_shards(text,integer,integer) + | function master_disable_node(text,integer) + | function master_dist_local_group_cache_invalidate() + | function master_dist_node_cache_invalidate() + | function master_dist_object_cache_invalidate() + | function master_dist_partition_cache_invalidate() + | function master_dist_placement_cache_invalidate() + | function master_dist_shard_cache_invalidate() + | function master_drain_node(text,integer,citus.shard_transfer_mode,name) + | function master_drop_all_shards(regclass,text,text) + | function master_drop_sequences(text[]) + | function master_get_active_worker_nodes() + | function master_get_new_placementid() + | function master_get_new_shardid() + | function master_get_table_ddl_events(text) + | function master_get_table_metadata(text) + | function master_modify_multiple_shards(text) + | function master_move_shard_placement(bigint,text,integer,text,integer,citus.shard_transfer_mode) + | function master_remove_distributed_table_metadata_from_workers(regclass,text,text) + | function master_remove_node(text,integer) + | function master_remove_partition_metadata(regclass,text,text) + | function master_run_on_worker(text[],integer[],text[],boolean) + | function master_set_node_property(text,integer,text,boolean) + | function master_unmark_object_distributed(oid,oid,integer) + | function master_update_node(integer,text,integer,boolean,integer) + | function master_update_shard_statistics(bigint) + | function master_update_table_statistics(regclass) + | function poolinfo_valid(text) + | function read_intermediate_result(text,citus_copy_format) + | function read_intermediate_results(text[],citus_copy_format) + | function rebalance_table_shards(regclass,real,integer,bigint[],citus.shard_transfer_mode,boolean,name) + | function recover_prepared_transactions() + | function relation_is_a_known_shard(regclass) + | function replicate_table_shards(regclass,integer,integer,bigint[],citus.shard_transfer_mode) + | function role_exists(name) + | function run_command_on_colocated_placements(regclass,regclass,text,boolean) + | function run_command_on_placements(regclass,text,boolean) + | function run_command_on_shards(regclass,text,boolean) + | function run_command_on_workers(text,boolean) + | function shard_name(regclass,bigint) + | function start_metadata_sync_to_node(text,integer) + | function stop_metadata_sync_to_node(text,integer) + | function task_tracker_assign_task(bigint,integer,text) + | function task_tracker_cleanup_job(bigint) + | function task_tracker_conninfo_cache_invalidate() + | function task_tracker_task_status(bigint,integer) + | function upgrade_to_reference_table(regclass) + | function worker_append_table_to_shard(text,text,text,integer) + | function worker_apply_inter_shard_ddl_command(bigint,text,bigint,text,text) + | function worker_apply_sequence_command(text) + | function worker_apply_sequence_command(text,regtype) + | function worker_apply_shard_ddl_command(bigint,text) + | function worker_apply_shard_ddl_command(bigint,text,text) + | function worker_cleanup_job_schema_cache() + | function worker_create_or_replace_object(text) + | function worker_create_schema(bigint,text) + | function worker_create_truncate_trigger(regclass) + | function worker_drop_distributed_table(text) + | function worker_execute_sql_task(bigint,integer,text,boolean) + | function worker_fetch_foreign_file(text,text,bigint,text[],integer[]) + | function worker_fetch_partition_file(bigint,integer,integer,integer,text,integer) + | function worker_hash("any") + | function worker_hash_partition_table(bigint,integer,text,text,oid,anyarray) + | function worker_merge_files_and_run_query(bigint,integer,text,text) + | function worker_merge_files_into_table(bigint,integer,text[],text[]) + | function worker_partial_agg(oid,anyelement) + | function worker_partial_agg_ffunc(internal) + | function worker_partial_agg_sfunc(internal,oid,anyelement) + | function worker_partition_query_result(text,text,integer,citus.distribution_type,text[],text[],boolean) + | function worker_range_partition_table(bigint,integer,text,text,oid,anyarray) + | function worker_repartition_cleanup(bigint) + | schema citus + | schema citus_internal + | sequence pg_dist_colocationid_seq + | sequence pg_dist_groupid_seq + | sequence pg_dist_node_nodeid_seq + | sequence pg_dist_placement_placementid_seq + | sequence pg_dist_shardid_seq + | table citus.pg_dist_object + | table pg_dist_authinfo + | table pg_dist_colocation + | table pg_dist_local_group + | table pg_dist_node + | table pg_dist_node_metadata + | table pg_dist_partition + | table pg_dist_placement + | table pg_dist_poolinfo + | table pg_dist_rebalance_strategy + | table pg_dist_shard + | table pg_dist_transaction + | type citus.distribution_type + | type citus.shard_transfer_mode + | type citus_copy_format + | type noderole + | view citus_dist_stat_activity + | view citus_lock_waits + | view citus_shard_indexes_on_worker + | view citus_shards_on_worker + | view citus_stat_statements + | view citus_worker_stat_activity + | view pg_dist_shard_placement +(188 rows) + +-- Test downgrade to 9.2-2 from 9.2-4 +ALTER EXTENSION citus UPDATE TO '9.2-4'; +ALTER EXTENSION citus UPDATE TO '9.2-2'; +-- Should be empty result since upgrade+downgrade should be a no-op +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- +(0 rows) + +/* + * As we mistakenly bumped schema version to 9.3-1 in a bad release, we support + * updating citus schema from 9.3-1 to 9.2-4, but we do not support updates to 9.3-1. + * + * Hence the query below should fail. + */ +ALTER EXTENSION citus UPDATE TO '9.3-1'; +ERROR: extension "citus" has no update path from version "9.2-2" to version "9.3-1" +ALTER EXTENSION citus UPDATE TO '9.2-4'; +-- Snapshot of state at 9.2-4 +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- +(0 rows) + +-- Test downgrade to 9.2-4 from 9.3-2 +ALTER EXTENSION citus UPDATE TO '9.3-2'; +ALTER EXTENSION citus UPDATE TO '9.2-4'; +-- Should be empty result since upgrade+downgrade should be a no-op +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- +(0 rows) + +-- Snapshot of state at 9.3-2 +ALTER EXTENSION citus UPDATE TO '9.3-2'; +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- + | function citus_remote_connection_stats() + | function replicate_reference_tables() + | function truncate_local_data_after_distributing_table(regclass) + | function update_distributed_table_colocation(regclass,text) + | function worker_create_or_alter_role(text,text,text) +(5 rows) + +-- Test downgrade to 9.3-2 from 9.4-1 +ALTER EXTENSION citus UPDATE TO '9.4-1'; +ALTER EXTENSION citus UPDATE TO '9.3-2'; +-- Should be empty result since upgrade+downgrade should be a no-op +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- +(0 rows) + +-- Snapshot of state at 9.4-1 +ALTER EXTENSION citus UPDATE TO '9.4-1'; +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- + | function worker_last_saved_explain_analyze() + | function worker_save_query_explain_analyze(text,jsonb) +(2 rows) + +-- Test downgrade to 9.4-1 from 9.5-1 +ALTER EXTENSION citus UPDATE TO '9.5-1'; +BEGIN; + SELECT master_add_node('localhost', :master_port, groupId=>0); + master_add_node +--------------------------------------------------------------------- + 1 +(1 row) + + CREATE TABLE citus_local_table (a int); + SELECT create_citus_local_table('citus_local_table'); + create_citus_local_table +--------------------------------------------------------------------- + +(1 row) + + -- downgrade from 9.5-1 to 9.4-1 should fail as we have a citus local table + ALTER EXTENSION citus UPDATE TO '9.4-1'; +ERROR: citus local tables are introduced in Citus 9.5 +HINT: To downgrade Citus to an older version, you should first convert each citus local table to a postgres table by executing SELECT undistribute_table("%s") +CONTEXT: PL/pgSQL function inline_code_block line 11 at RAISE +ROLLBACK; +-- now we can downgrade as there is no citus local table +ALTER EXTENSION citus UPDATE TO '9.4-1'; +-- Should be empty result since upgrade+downgrade should be a no-op +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- +(0 rows) + +-- Snapshot of state at 9.5-1 +ALTER EXTENSION citus UPDATE TO '9.5-1'; +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- + function master_drop_sequences(text[]) | + function task_tracker_assign_task(bigint,integer,text) | + function task_tracker_cleanup_job(bigint) | + function task_tracker_conninfo_cache_invalidate() | + function task_tracker_task_status(bigint,integer) | + function worker_execute_sql_task(bigint,integer,text,boolean) | + function worker_merge_files_and_run_query(bigint,integer,text,text) | + | function create_citus_local_table(regclass) + | function undistribute_table(regclass) + | function worker_record_sequence_dependency(regclass,regclass,name) +(10 rows) + +-- Test downgrade to 9.5-1 from 10.0-1 +ALTER EXTENSION citus UPDATE TO '10.0-1'; +ALTER EXTENSION citus UPDATE TO '9.5-1'; +-- Should be empty result since upgrade+downgrade should be a no-op +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- +(0 rows) + +-- Snapshot of state at 10.0-1 +ALTER EXTENSION citus UPDATE TO '10.0-1'; +SELECT * FROM print_extension_changes(); + previous_object | current_object +--------------------------------------------------------------------- + | event trigger cstore_ddl_event_end + | foreign-data wrapper cstore_fdw + | function citus_internal.cstore_ensure_objects_exist() + | function cstore.cstore_ddl_event_end_trigger() + | function cstore.cstore_fdw_handler() + | function cstore.cstore_fdw_validator(text[],oid) + | function cstore_table_size(regclass) + | schema cstore + | table cstore.cstore_data_files + | table cstore.cstore_skipnodes + | table cstore.cstore_stripes + | view cstore.cstore_options +(12 rows) + +DROP TABLE prev_objects, extension_diff; +-- show running version +SHOW citus.version; + citus.version +--------------------------------------------------------------------- + 10.0devel +(1 row) + +-- ensure no objects were created outside pg_catalog +SELECT COUNT(*) +FROM pg_depend AS pgd, + pg_extension AS pge, + LATERAL pg_identify_object(pgd.classid, pgd.objid, pgd.objsubid) AS pgio +WHERE pgd.refclassid = 'pg_extension'::regclass AND + pgd.refobjid = pge.oid AND + pge.extname = 'citus' AND + pgio.schema NOT IN ('pg_catalog', 'citus', 'citus_internal', 'test', 'cstore'); + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- see incompatible version errors out +RESET citus.enable_version_checks; +DROP EXTENSION citus; +CREATE EXTENSION citus VERSION '7.0-1'; +ERROR: specified version incompatible with loaded Citus library +DETAIL: Loaded library requires 10.0, but 7.0-1 was specified. +HINT: If a newer library is present, restart the database and try the command again. +-- Test non-distributed queries work even in version mismatch +SET citus.enable_version_checks TO 'false'; +CREATE EXTENSION citus VERSION '7.1-1'; +SET citus.enable_version_checks TO 'true'; +-- Test CREATE TABLE +CREATE TABLE version_mismatch_table(column1 int); +-- Test COPY +\copy version_mismatch_table FROM STDIN; +-- Test INSERT +INSERT INTO version_mismatch_table(column1) VALUES(5); +-- Test SELECT +SELECT * FROM version_mismatch_table ORDER BY column1; + column1 +--------------------------------------------------------------------- + 0 + 1 + 2 + 3 + 4 + 5 +(6 rows) + +-- Test SELECT from pg_catalog +SELECT d.datname as "Name", + pg_catalog.pg_get_userbyid(d.datdba) as "Owner", + pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" +FROM pg_catalog.pg_database d +ORDER BY 1; + Name | Owner | Access privileges +--------------------------------------------------------------------- + postgres | postgres | + regression | postgres | + template0 | postgres | =c/postgres + + | | postgres=CTc/postgres + template1 | postgres | =c/postgres + + | | postgres=CTc/postgres +(4 rows) + +-- We should not distribute table in version mistmatch +SELECT create_distributed_table('version_mismatch_table', 'column1'); +ERROR: loaded Citus library version differs from installed extension version +DETAIL: Loaded library requires 10.0, but the installed extension version is 7.1-1. +HINT: Run ALTER EXTENSION citus UPDATE and try again. +-- This function will cause fail in next ALTER EXTENSION +CREATE OR REPLACE FUNCTION pg_catalog.master_dist_authinfo_cache_invalidate() +RETURNS void LANGUAGE plpgsql +AS $function$ +BEGIN +END; +$function$; +SET citus.enable_version_checks TO 'false'; +-- This will fail because of previous function declaration +ALTER EXTENSION citus UPDATE TO '8.1-1'; +ERROR: function "master_dist_authinfo_cache_invalidate" already exists with same argument types +-- We can DROP problematic function and continue ALTER EXTENSION even when version checks are on +SET citus.enable_version_checks TO 'true'; +DROP FUNCTION pg_catalog.master_dist_authinfo_cache_invalidate(); +SET citus.enable_version_checks TO 'false'; +ALTER EXTENSION citus UPDATE TO '8.1-1'; +-- Test updating to the latest version without specifying the version number +ALTER EXTENSION citus UPDATE; +-- re-create in newest version +DROP EXTENSION citus; +\c +CREATE EXTENSION citus; +-- test cache invalidation in workers +\c - - - :worker_1_port +DROP EXTENSION citus; +SET citus.enable_version_checks TO 'false'; +CREATE EXTENSION citus VERSION '7.0-1'; +SET citus.enable_version_checks TO 'true'; +-- during ALTER EXTENSION, we should invalidate the cache +ALTER EXTENSION citus UPDATE; +-- if cache is invalidated succesfull, this \d should work without any problem +\d + List of relations + Schema | Name | Type | Owner +--------------------------------------------------------------------- +(0 rows) + +\c - - - :master_port +-- test https://github.com/citusdata/citus/issues/3409 +CREATE USER testuser2 SUPERUSER; +NOTICE: not propagating CREATE ROLE/USER commands to worker nodes +HINT: Connect to worker nodes directly to manually create all necessary users and roles. +SET ROLE testuser2; +DROP EXTENSION Citus; +-- Loop until we see there's no maintenance daemon running +DO $$begin + for i in 0 .. 100 loop + if i = 100 then raise 'Waited too long'; end if; + PERFORM pg_stat_clear_snapshot(); + perform * from pg_stat_activity where application_name = 'Citus Maintenance Daemon'; + if not found then exit; end if; + perform pg_sleep(0.1); + end loop; +end$$; +SELECT datid, datname, usename FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + datid | datname | usename +--------------------------------------------------------------------- +(0 rows) + +CREATE EXTENSION Citus; +-- Loop until we there's a maintenance daemon running +DO $$begin + for i in 0 .. 100 loop + if i = 100 then raise 'Waited too long'; end if; + PERFORM pg_stat_clear_snapshot(); + perform * from pg_stat_activity where application_name = 'Citus Maintenance Daemon'; + if found then exit; end if; + perform pg_sleep(0.1); + end loop; +end$$; +SELECT datid, datname, usename FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + datid | datname | usename +--------------------------------------------------------------------- + 16384 | regression | testuser2 +(1 row) + +RESET ROLE; +-- check that maintenance daemon gets (re-)started for the right user +DROP EXTENSION citus; +CREATE USER testuser SUPERUSER; +SET ROLE testuser; +CREATE EXTENSION citus; +SELECT datname, current_database(), + usename, (SELECT extowner::regrole::text FROM pg_extension WHERE extname = 'citus') +FROM test.maintenance_worker(); + datname | current_database | usename | extowner +--------------------------------------------------------------------- + regression | regression | testuser | testuser +(1 row) + +-- and recreate as the right owner +RESET ROLE; +DROP EXTENSION citus; +CREATE EXTENSION citus; +-- Check that maintenance daemon can also be started in another database +CREATE DATABASE another; +NOTICE: Citus partially supports CREATE DATABASE for distributed databases +DETAIL: Citus does not propagate CREATE DATABASE command to workers +HINT: You can manually create a database and its extensions on workers. +\c another +CREATE EXTENSION citus; +CREATE SCHEMA test; +:create_function_test_maintenance_worker +-- see that the daemon started +SELECT datname, current_database(), + usename, (SELECT extowner::regrole::text FROM pg_extension WHERE extname = 'citus') +FROM test.maintenance_worker(); + datname | current_database | usename | extowner +--------------------------------------------------------------------- + another | another | postgres | postgres +(1 row) + +-- Test that database with active worker can be dropped. +\c regression +CREATE SCHEMA test_daemon; +-- we create a similar function on the regression database +-- note that this function checks for the existence of the daemon +-- when not found, returns true else tries for 5 times and +-- returns false +CREATE OR REPLACE FUNCTION test_daemon.maintenance_daemon_died(p_dbname text) + RETURNS boolean + LANGUAGE plpgsql +AS $$ +DECLARE + activity record; +BEGIN + PERFORM pg_stat_clear_snapshot(); + SELECT * INTO activity FROM pg_stat_activity + WHERE application_name = 'Citus Maintenance Daemon' AND datname = p_dbname; + IF activity.pid IS NULL THEN + RETURN true; + ELSE + RETURN false; + END IF; +END; +$$; +-- drop the database and see that the daemon is dead +DROP DATABASE another; +SELECT + * +FROM + test_daemon.maintenance_daemon_died('another'); + maintenance_daemon_died +--------------------------------------------------------------------- + t +(1 row) + +-- we don't need the schema and the function anymore +DROP SCHEMA test_daemon CASCADE; +NOTICE: drop cascades to function test_daemon.maintenance_daemon_died(text) +-- verify citus does not crash while creating a table when run against an older worker +-- create_distributed_table piggybacks multiple commands into single one, if one worker +-- did not have the required UDF it should fail instead of crash. +-- create a test database, configure citus with single node +CREATE DATABASE another; +NOTICE: Citus partially supports CREATE DATABASE for distributed databases +DETAIL: Citus does not propagate CREATE DATABASE command to workers +HINT: You can manually create a database and its extensions on workers. +\c - - - :worker_1_port +CREATE DATABASE another; +NOTICE: Citus partially supports CREATE DATABASE for distributed databases +DETAIL: Citus does not propagate CREATE DATABASE command to workers +HINT: You can manually create a database and its extensions on workers. +\c - - - :master_port +\c another +CREATE EXTENSION citus; +SET citus.enable_object_propagation TO off; -- prevent distributed transactions during add node +SELECT FROM master_add_node('localhost', :worker_1_port); +WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker +DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created +-- +(1 row) + +\c - - - :worker_1_port +CREATE EXTENSION citus; +ALTER FUNCTION assign_distributed_transaction_id(initiator_node_identifier integer, transaction_number bigint, transaction_stamp timestamp with time zone) +RENAME TO dummy_assign_function; +\c - - - :master_port +SET citus.shard_replication_factor to 1; +-- create_distributed_table command should fail +CREATE TABLE t1(a int, b int); +SET client_min_messages TO ERROR; +DO $$ +BEGIN + BEGIN + SELECT create_distributed_table('t1', 'a'); + EXCEPTION WHEN OTHERS THEN + RAISE 'create distributed table failed'; + END; +END; +$$; +ERROR: create distributed table failed +CONTEXT: PL/pgSQL function inline_code_block line 6 at RAISE +\c regression +\c - - - :master_port +DROP DATABASE another; +\c - - - :worker_1_port +DROP DATABASE another; +\c - - - :master_port +-- only the regression database should have a maintenance daemon +SELECT count(*) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + count +--------------------------------------------------------------------- + 1 +(1 row) + +-- recreate the extension immediately after the maintenancae daemon errors +SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + pg_cancel_backend +--------------------------------------------------------------------- + t +(1 row) + +DROP EXTENSION citus; +CREATE EXTENSION citus; +-- wait for maintenance daemon restart +SELECT datname, current_database(), + usename, (SELECT extowner::regrole::text FROM pg_extension WHERE extname = 'citus') +FROM test.maintenance_worker(); + datname | current_database | usename | extowner +--------------------------------------------------------------------- + regression | regression | postgres | postgres +(1 row) + +-- confirm that there is only one maintenance daemon +SELECT count(*) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + count +--------------------------------------------------------------------- + 1 +(1 row) + +-- kill the maintenance daemon +SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + pg_cancel_backend +--------------------------------------------------------------------- + t +(1 row) + +-- reconnect +\c - - - :master_port +-- run something that goes through planner hook and therefore kicks of maintenance daemon +SELECT 1; + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +-- wait for maintenance daemon restart +SELECT datname, current_database(), + usename, (SELECT extowner::regrole::text FROM pg_extension WHERE extname = 'citus') +FROM test.maintenance_worker(); + datname | current_database | usename | extowner +--------------------------------------------------------------------- + regression | regression | postgres | postgres +(1 row) + +-- confirm that there is only one maintenance daemon +SELECT count(*) FROM pg_stat_activity WHERE application_name = 'Citus Maintenance Daemon'; + count +--------------------------------------------------------------------- + 1 +(1 row) + +DROP TABLE version_mismatch_table; diff --git a/src/test/regress/sql/multi_extension.sql b/src/test/regress/sql/multi_extension.sql index 4444bb5f4..515c66b71 100644 --- a/src/test/regress/sql/multi_extension.sql +++ b/src/test/regress/sql/multi_extension.sql @@ -6,6 +6,11 @@ -- It'd be nice to script generation of this file, but alas, that's -- not done yet. +-- differentiate the output file for pg11 and versions above, with regards to objects +-- created per citus version depending on the postgres version. Upgrade tests verify the +-- objects are added in citus_finish_pg_upgrade() +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 11 AS version_above_eleven; SET citus.next_shard_id TO 580000;