citus/src/test/regress/expected/view_propagation.out

441 lines
21 KiB
Plaintext

-- Tests to check propagation of all view commands
CREATE SCHEMA view_prop_schema;
SET search_path to view_prop_schema;
-- Check creating views depending on different types of tables
-- and from multiple schemas
-- Check the most basic one
CREATE VIEW prop_view_basic AS SELECT 1;
-- Try to create view depending local table, then try to recreate it after distributing the table
CREATE TABLE view_table_1(id int, val_1 text);
CREATE VIEW prop_view_1 AS
SELECT * FROM view_table_1;
WARNING: "view prop_view_1" has dependency to "table view_table_1" that is not in Citus' metadata
DETAIL: "view prop_view_1" will be created only locally
HINT: Distribute "table view_table_1" first to distribute "view prop_view_1"
SELECT create_distributed_table('view_table_1', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE VIEW prop_view_1 AS
SELECT * FROM view_table_1;
-- Try to create view depending local table, then try to recreate it after making the table reference table
CREATE TABLE view_table_2(id int PRIMARY KEY, val_1 text);
CREATE VIEW prop_view_2 AS
SELECT view_table_1.id, view_table_2.val_1 FROM view_table_1 INNER JOIN view_table_2
ON view_table_1.id = view_table_2.id;
WARNING: "view prop_view_2" has dependency to "table view_table_2" that is not in Citus' metadata
DETAIL: "view prop_view_2" will be created only locally
HINT: Distribute "table view_table_2" first to distribute "view prop_view_2"
SELECT create_reference_table('view_table_2');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE VIEW prop_view_2 AS
SELECT view_table_1.id, view_table_2.val_1 FROM view_table_1 INNER JOIN view_table_2
ON view_table_1.id = view_table_2.id;
-- Try to create view depending local table, then try to recreate it after making the table citus local table
CREATE TABLE view_table_3(id int, val_1 text);
CREATE VIEW prop_view_3 AS
SELECT * FROM view_table_1 WHERE id IN
(SELECT view_table_2.id FROM view_table_2 INNER JOIN view_table_3 ON view_table_2.id = view_table_3.id);
WARNING: "view prop_view_3" has dependency to "table view_table_3" that is not in Citus' metadata
DETAIL: "view prop_view_3" will be created only locally
HINT: Distribute "table view_table_3" first to distribute "view prop_view_3"
SET client_min_messages TO WARNING;
SELECT 1 FROM citus_add_node('localhost', :master_port, groupid=>0);
?column?
---------------------------------------------------------------------
1
(1 row)
RESET client_min_messages;
ALTER TABLE view_table_3
ADD CONSTRAINT f_key_for_local_table
FOREIGN KEY(id)
REFERENCES view_table_2(id);
CREATE OR REPLACE VIEW prop_view_3 AS
SELECT * FROM view_table_1 WHERE id IN
(SELECT view_table_2.id FROM view_table_2 INNER JOIN view_table_3 ON view_table_2.id = view_table_3.id);
-- Try to create view depending on PG metadata table
CREATE VIEW prop_view_4 AS
SELECT * FROM pg_stat_activity;
-- Try to create view depending on Citus metadata table
CREATE VIEW prop_view_5 AS
SELECT * FROM citus_dist_stat_activity;
-- Try to create table depending on a local table from another schema, then try to create it again after distributing the table
CREATE SCHEMA view_prop_schema_inner;
SET search_path TO view_prop_schema_inner;
-- Create local table for tests below
CREATE TABLE view_table_4(id int, val_1 text);
-- Create a distributed table and view to test drop view below
CREATE TABLE inner_view_table(id int);
SELECT create_distributed_table('inner_view_table','id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE VIEW inner_view_prop AS SELECT * FROM inner_view_table;
SET search_path to view_prop_schema;
CREATE VIEW prop_view_6 AS
SELECT vt1.id, vt4.val_1 FROM view_table_1 AS vt1
INNER JOIN view_prop_schema_inner.view_table_4 AS vt4 ON vt1.id = vt4.id;
WARNING: "view prop_view_6" has dependency to "table view_prop_schema_inner.view_table_4" that is not in Citus' metadata
DETAIL: "view prop_view_6" will be created only locally
HINT: Distribute "table view_prop_schema_inner.view_table_4" first to distribute "view prop_view_6"
SELECT create_distributed_table('view_prop_schema_inner.view_table_4','id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE VIEW prop_view_6 AS
SELECT vt1.id, vt4.val_1 FROM view_table_1 AS vt1
INNER JOIN view_prop_schema_inner.view_table_4 AS vt4 ON vt1.id = vt4.id;
-- Show that all views are propagated as distributed object
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_%' ORDER BY 1;
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,prop_view_1}",{})
(view,"{view_prop_schema,prop_view_2}",{})
(view,"{view_prop_schema,prop_view_3}",{})
(view,"{view_prop_schema,prop_view_4}",{})
(view,"{view_prop_schema,prop_view_5}",{})
(view,"{view_prop_schema,prop_view_6}",{})
(view,"{view_prop_schema,prop_view_basic}",{})
(7 rows)
-- Check creating views depending various kind of objects
-- Tests will also check propagating dependent objects
-- Depending on function
SET citus.enable_ddl_propagation TO OFF;
CREATE OR REPLACE FUNCTION func_1_for_view(param_1 int)
RETURNS int
LANGUAGE plpgsql AS
$$
BEGIN
return param_1;
END;
$$;
RESET citus.enable_ddl_propagation;
-- Show that function will be propagated together with the view
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%func_1_for_view%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
CREATE VIEW prop_view_7 AS SELECT func_1_for_view(id) FROM view_table_1;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%func_1_for_view%';
obj_identifier
---------------------------------------------------------------------
(function,"{view_prop_schema,func_1_for_view}",{integer})
(1 row)
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_7%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,prop_view_7}",{})
(1 row)
-- Depending on type
SET citus.enable_ddl_propagation TO OFF;
CREATE TYPE type_for_view_prop AS ENUM ('a','b','c');
RESET citus.enable_ddl_propagation;
-- Show that type will be propagated together with the view
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%type_for_view_prop%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
CREATE VIEW prop_view_8 AS SELECT val_1::type_for_view_prop FROM view_table_1;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%type_for_view_prop%';
obj_identifier
---------------------------------------------------------------------
(type,{view_prop_schema.type_for_view_prop},{})
(1 row)
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_8%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,prop_view_8}",{})
(1 row)
-- Depending on another view
CREATE TABLE view_table_5(id int);
CREATE VIEW prop_view_9 AS SELECT * FROM view_table_5;
WARNING: "view prop_view_9" has dependency to "table view_table_5" that is not in Citus' metadata
DETAIL: "view prop_view_9" will be created only locally
HINT: Distribute "table view_table_5" first to distribute "view prop_view_9"
CREATE VIEW prop_view_10 AS SELECT * FROM prop_view_9;
WARNING: "view prop_view_10" has dependency to "table view_table_5" that is not in Citus' metadata
DETAIL: "view prop_view_10" will be created only locally
HINT: Distribute "table view_table_5" first to distribute "view prop_view_10"
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_9%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_10%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
SELECT create_distributed_table('view_table_5', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE VIEW prop_view_10 AS SELECT * FROM prop_view_9;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_9%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,prop_view_9}",{})
(1 row)
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_10%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,prop_view_10}",{})
(1 row)
-- Check views owned by non-superuser
SET client_min_messages TO ERROR;
CREATE USER view_creation_user;
SELECT 1 FROM run_command_on_workers($$CREATE USER view_creation_user;$$);
?column?
---------------------------------------------------------------------
1
1
(2 rows)
GRANT ALL PRIVILEGES ON SCHEMA view_prop_schema to view_creation_user;
SET ROLE view_creation_user;
CREATE TABLE user_owned_table_for_view(id int);
SELECT create_distributed_table('user_owned_table_for_view','id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE VIEW view_owned_by_user AS SELECT * FROM user_owned_table_for_view;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%view_owned_by_user%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,view_owned_by_user}",{})
(1 row)
DROP VIEW view_owned_by_user;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%view_owned_by_user%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
DROP TABLE user_owned_table_for_view;
RESET ROLE;
RESET client_min_messages;
-- Create view with different options
CREATE TABLE view_table_6(id int, val_1 text);
SELECT create_distributed_table('view_table_6','id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- TEMP VIEW is not supported. View will be created locally.
CREATE TEMP VIEW temp_prop_view AS SELECT * FROM view_table_6;
WARNING: "view temp_prop_view" has dependency on unsupported object "schema pg_temp_xxx"
DETAIL: "view temp_prop_view" will be created only locally
-- Recursive views are supported
CREATE RECURSIVE VIEW nums_1_100_prop_view (n) AS
VALUES (1)
UNION ALL
SELECT n+1 FROM nums_1_100_prop_view WHERE n < 100;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%nums_1_100_prop_view%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,nums_1_100_prop_view}",{})
(1 row)
-- Sequences are supported as dependency
CREATE SEQUENCE sequence_to_prop;
CREATE VIEW seq_view_prop AS SELECT sequence_to_prop.is_called FROM sequence_to_prop;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%sequence_to_prop%';
obj_identifier
---------------------------------------------------------------------
(sequence,"{view_prop_schema,sequence_to_prop}",{})
(1 row)
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%seq_view_prop%';
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,seq_view_prop}",{})
(1 row)
-- Views depend on temp sequences will be created locally
CREATE TEMPORARY SEQUENCE temp_sequence_to_drop;
CREATE VIEW temp_seq_view_prop AS SELECT temp_sequence_to_drop.is_called FROM temp_sequence_to_drop;
NOTICE: view "temp_seq_view_prop" will be a temporary view
WARNING: "view temp_seq_view_prop" has dependency on unsupported object "schema pg_temp_xxx"
DETAIL: "view temp_seq_view_prop" will be created only locally
-- Check circular dependencies are detected
CREATE VIEW circular_view_1 AS SELECT * FROM view_table_6;
CREATE VIEW circular_view_2 AS SELECT * FROM view_table_6;
CREATE OR REPLACE VIEW circular_view_1 AS SELECT view_table_6.* FROM view_table_6 JOIN circular_view_2 USING (id);
CREATE OR REPLACE VIEW circular_view_2 AS SELECT view_table_6.* FROM view_table_6 JOIN circular_view_1 USING (id);
ERROR: Citus can not handle circular dependencies between distributed objects
DETAIL: "view circular_view_2" circularly depends itself, resolve circular dependency first
-- Recursive views with distributed tables included
CREATE TABLE employees (employee_id int, manager_id int, full_name text);
SELECT create_distributed_table('employees', 'employee_id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE RECURSIVE VIEW reporting_line (employee_id, subordinates) AS
SELECT
employee_id,
full_name AS subordinates
FROM
employees
WHERE
manager_id IS NULL
UNION ALL
SELECT
e.employee_id,
(
rl.subordinates || ' > ' || e.full_name
) AS subordinates
FROM
employees e
INNER JOIN reporting_line rl ON e.manager_id = rl.employee_id;
-- Aliases are supported
CREATE VIEW aliased_opt_prop_view(alias_1, alias_2) AS SELECT * FROM view_table_6;
-- View options are supported
CREATE VIEW opt_prop_view
WITH(check_option=CASCADED, security_barrier=true)
AS SELECT * FROM view_table_6;
CREATE VIEW sep_opt_prop_view
AS SELECT * FROM view_table_6
WITH LOCAL CHECK OPTION;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%opt_prop_view%' ORDER BY 1;
obj_identifier
---------------------------------------------------------------------
(view,"{view_prop_schema,aliased_opt_prop_view}",{})
(view,"{view_prop_schema,opt_prop_view}",{})
(view,"{view_prop_schema,sep_opt_prop_view}",{})
(3 rows)
-- Check definitions and reltoptions of views are correct on workers
\c - - - :worker_1_port
SELECT definition FROM pg_views WHERE viewname = 'aliased_opt_prop_view';
definition
---------------------------------------------------------------------
SELECT view_table_6.id AS alias_1, +
view_table_6.val_1 AS alias_2 +
FROM view_prop_schema.view_table_6;
(1 row)
SELECT definition FROM pg_views WHERE viewname = 'opt_prop_view';
definition
---------------------------------------------------------------------
SELECT view_table_6.id, +
view_table_6.val_1 +
FROM view_prop_schema.view_table_6;
(1 row)
SELECT definition FROM pg_views WHERE viewname = 'sep_opt_prop_view';
definition
---------------------------------------------------------------------
SELECT view_table_6.id, +
view_table_6.val_1 +
FROM view_prop_schema.view_table_6;
(1 row)
SELECT relname, reloptions
FROM pg_class
WHERE
oid = 'view_prop_schema.aliased_opt_prop_view'::regclass::oid OR
oid = 'view_prop_schema.opt_prop_view'::regclass::oid OR
oid = 'view_prop_schema.sep_opt_prop_view'::regclass::oid
ORDER BY 1;
relname | reloptions
---------------------------------------------------------------------
aliased_opt_prop_view |
opt_prop_view | {check_option=cascaded,security_barrier=true}
sep_opt_prop_view | {check_option=local}
(3 rows)
\c - - - :master_port
SET search_path to view_prop_schema;
-- Sync metadata to check it works properly after adding a view
SELECT start_metadata_sync_to_node('localhost', :worker_1_port);
start_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
-- Drop views and check metadata afterwards
DROP VIEW prop_view_9 CASCADE;
NOTICE: drop cascades to view prop_view_10
DROP VIEW opt_prop_view, aliased_opt_prop_view, view_prop_schema_inner.inner_view_prop, sep_opt_prop_view;
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%inner_view_prop%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%opt_prop_view%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
-- Drop a column that view depends on
ALTER TABLE view_table_1 DROP COLUMN val_1 CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to view prop_view_1
drop cascades to view prop_view_3
drop cascades to view prop_view_8
-- Since prop_view_3 depends on the view_table_1's val_1 column, it should be dropped
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_3%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
-- Drop a table that view depends on
DROP TABLE view_table_2 CASCADE;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to view prop_view_2
drop cascades to constraint f_key_for_local_table on table view_table_3
NOTICE: drop cascades to constraint f_key_for_local_table_1410200 on table view_prop_schema.view_table_3_1410200
CONTEXT: SQL statement "SELECT citus_drop_all_shards(v_obj.objid, v_obj.schema_name, v_obj.object_name, drop_shards_metadata_only := false)"
PL/pgSQL function citus_drop_trigger() line XX at PERFORM
NOTICE: removing table view_prop_schema.view_table_3 from metadata as it is not connected to any reference tables via foreign keys
-- Since prop_view_2 depends on the view_table_2, it should be dropped
SELECT * FROM (SELECT pg_identify_object_as_address(classid, objid, objsubid) as obj_identifier from pg_catalog.pg_dist_object) as obj_identifiers where obj_identifier::text like '%prop_view_2%';
obj_identifier
---------------------------------------------------------------------
(0 rows)
-- Show that unsupported CREATE OR REPLACE VIEW commands are catched by PG on the coordinator
CREATE TABLE table_to_test_unsup_view(id int, val1 text);
SELECT create_distributed_table('table_to_test_unsup_view', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE VIEW view_for_unsup_commands AS SELECT * FROM table_to_test_unsup_view;
CREATE OR REPLACE VIEW view_for_unsup_commands(a,b) AS SELECT * FROM table_to_test_unsup_view;
ERROR: cannot change name of view column "id" to "a"
HINT: Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead.
CREATE OR REPLACE VIEW view_for_unsup_commands AS SELECT id FROM table_to_test_unsup_view;
ERROR: cannot drop columns from view
SET client_min_messages TO ERROR;
DROP SCHEMA view_prop_schema_inner CASCADE;
DROP SCHEMA view_prop_schema CASCADE;