mirror of https://github.com/citusdata/citus.git
Error out for views with circular dependencies (#6051)
Adds error check for views with circular dependenciespull/6090/head
parent
b08e5ec29d
commit
2b2a529653
|
@ -202,12 +202,12 @@ ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DeferErrorIfCircularDependencyExists checks whether given object has
|
* DeferErrorIfCircularDependencyExists checks whether given object has
|
||||||
* circular dependency with itself via existing objects of pg_dist_object.
|
* circular dependency with itself. If so, returns a deferred error.
|
||||||
*/
|
*/
|
||||||
DeferredErrorMessage *
|
DeferredErrorMessage *
|
||||||
DeferErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
|
DeferErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
|
||||||
{
|
{
|
||||||
List *dependencies = GetAllSupportedDependenciesForObject(objectAddress);
|
List *dependencies = GetAllDependenciesForObject(objectAddress);
|
||||||
|
|
||||||
ObjectAddress *dependency = NULL;
|
ObjectAddress *dependency = NULL;
|
||||||
foreach_ptr(dependency, dependencies)
|
foreach_ptr(dependency, dependencies)
|
||||||
|
|
|
@ -1615,7 +1615,7 @@ ExpandCitusSupportedTypes(ObjectAddressCollector *collector, ObjectAddress targe
|
||||||
* rule and that rule has dependencies to other objects.
|
* rule and that rule has dependencies to other objects.
|
||||||
*/
|
*/
|
||||||
char relKind = get_rel_relkind(relationId);
|
char relKind = get_rel_relkind(relationId);
|
||||||
if (relKind == RELKIND_VIEW)
|
if (relKind == RELKIND_VIEW || relKind == RELKIND_MATVIEW)
|
||||||
{
|
{
|
||||||
List *ruleRefDepList = GetViewRuleReferenceDependencyList(relationId);
|
List *ruleRefDepList = GetViewRuleReferenceDependencyList(relationId);
|
||||||
result = list_concat(result, ruleRefDepList);
|
result = list_concat(result, ruleRefDepList);
|
||||||
|
@ -2109,6 +2109,23 @@ GetDependingViews(Oid relationId)
|
||||||
ViewDependencyNode *dependingNode = NULL;
|
ViewDependencyNode *dependingNode = NULL;
|
||||||
foreach_ptr(dependingNode, node->dependingNodes)
|
foreach_ptr(dependingNode, node->dependingNodes)
|
||||||
{
|
{
|
||||||
|
ObjectAddress relationAddress = { 0 };
|
||||||
|
ObjectAddressSet(relationAddress, RelationRelationId, dependingNode->id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function does not catch views with circular dependencies,
|
||||||
|
* because of the remaining dependency count check below.
|
||||||
|
* Here we check if the view has a circular dependency or not.
|
||||||
|
* If yes, we error out with a message that tells the user that
|
||||||
|
* Citus does not handle circular dependencies.
|
||||||
|
*/
|
||||||
|
DeferredErrorMessage *depError =
|
||||||
|
DeferErrorIfCircularDependencyExists(&relationAddress);
|
||||||
|
if (depError != NULL)
|
||||||
|
{
|
||||||
|
RaiseDeferredError(depError, ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
dependingNode->remainingDependencyCount--;
|
dependingNode->remainingDependencyCount--;
|
||||||
if (dependingNode->remainingDependencyCount == 0)
|
if (dependingNode->remainingDependencyCount == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -882,8 +882,13 @@ CREATE MATERIALIZED VIEW matview_101 AS SELECT * from loc_tb;
|
||||||
CREATE VIEW v103 AS SELECT * from loc_tb;
|
CREATE VIEW v103 AS SELECT * from loc_tb;
|
||||||
CREATE MATERIALIZED VIEW matview_102 AS SELECT * from loc_tb JOIN v103 USING (a);
|
CREATE MATERIALIZED VIEW matview_102 AS SELECT * from loc_tb JOIN v103 USING (a);
|
||||||
CREATE OR REPLACE VIEW v103 AS SELECT * from loc_tb JOIN matview_102 USING (a);
|
CREATE OR REPLACE VIEW v103 AS SELECT * from loc_tb JOIN matview_102 USING (a);
|
||||||
|
-- fails to add local table to metadata, because of the circular dependency
|
||||||
|
ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a);
|
||||||
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
|
-- drop the view&matview with circular dependency
|
||||||
|
DROP VIEW v103 CASCADE;
|
||||||
SET client_min_messages TO DEBUG1;
|
SET client_min_messages TO DEBUG1;
|
||||||
-- auto undistribute
|
-- now it should successfully add to metadata and create the views on workers
|
||||||
ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a);
|
ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a);
|
||||||
DEBUG: executing "CREATE OR REPLACE VIEW citus_local_tables_mx.v100 (a) AS SELECT loc_tb.a
|
DEBUG: executing "CREATE OR REPLACE VIEW citus_local_tables_mx.v100 (a) AS SELECT loc_tb.a
|
||||||
FROM citus_local_tables_mx.loc_tb; ALTER VIEW citus_local_tables_mx.v100 OWNER TO postgres"
|
FROM citus_local_tables_mx.loc_tb; ALTER VIEW citus_local_tables_mx.v100 OWNER TO postgres"
|
||||||
|
@ -907,6 +912,7 @@ select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100,
|
||||||
(localhost,57638,t,0)
|
(localhost,57638,t,0)
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- auto undistribute
|
||||||
ALTER TABLE loc_tb DROP CONSTRAINT fkey;
|
ALTER TABLE loc_tb DROP CONSTRAINT fkey;
|
||||||
-- fails because fkey is dropped and table is converted to local table
|
-- fails because fkey is dropped and table is converted to local table
|
||||||
select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100$$);
|
select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100$$);
|
||||||
|
@ -1075,6 +1081,29 @@ SELECT count(*) FROM citus_local_tables_mx.mv4;
|
||||||
0
|
0
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- test circular dependency detection among views
|
||||||
|
create table root_tbl (a int);
|
||||||
|
create materialized view chain_v1 as select * from root_tbl;
|
||||||
|
create view chain_v2 as select * from chain_v1;
|
||||||
|
WARNING: "view chain_v2" has dependency to "table root_tbl" that is not in Citus' metadata
|
||||||
|
create materialized view chain_v3 as select * from chain_v2;
|
||||||
|
create or replace view chain_v2 as select * from chain_v1 join chain_v3 using (a);
|
||||||
|
WARNING: "view chain_v2" has dependency on unsupported object "materialized view chain_v3"
|
||||||
|
-- catch circular dependency and error out
|
||||||
|
select citus_add_local_table_to_metadata('root_tbl');
|
||||||
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
|
-- same for create_distributed_table
|
||||||
|
select create_distributed_table('root_tbl','a');
|
||||||
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
|
-- fix the circular dependency and add to metadata
|
||||||
|
create or replace view chain_v2 as select * from chain_v1;
|
||||||
|
WARNING: "view chain_v2" has dependency to "table root_tbl" that is not in Citus' metadata
|
||||||
|
select citus_add_local_table_to_metadata('root_tbl');
|
||||||
|
citus_add_local_table_to_metadata
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- todo: add more matview tests once 5968 and 6028 are fixed
|
-- todo: add more matview tests once 5968 and 6028 are fixed
|
||||||
-- cleanup at exit
|
-- cleanup at exit
|
||||||
set client_min_messages to error;
|
set client_min_messages to error;
|
||||||
|
|
|
@ -811,11 +811,8 @@ WARNING: "view v_test_2" has dependency to "table employees" that is not in Cit
|
||||||
DETAIL: "view v_test_2" will be created only locally
|
DETAIL: "view v_test_2" will be created only locally
|
||||||
HINT: Distribute "table employees" first to distribute "view v_test_2"
|
HINT: Distribute "table employees" first to distribute "view v_test_2"
|
||||||
SELECT create_distributed_table('employees','employee_id');
|
SELECT create_distributed_table('employees','employee_id');
|
||||||
create_distributed_table
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
---------------------------------------------------------------------
|
DETAIL: "view v_test_1" circularly depends itself, resolve circular dependency first
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- verify not distributed
|
-- verify not distributed
|
||||||
SELECT run_command_on_workers($$SELECT count(*) FROM v_test_1$$);
|
SELECT run_command_on_workers($$SELECT count(*) FROM v_test_1$$);
|
||||||
run_command_on_workers
|
run_command_on_workers
|
||||||
|
|
|
@ -460,14 +460,20 @@ CREATE VIEW v103 AS SELECT * from loc_tb;
|
||||||
CREATE MATERIALIZED VIEW matview_102 AS SELECT * from loc_tb JOIN v103 USING (a);
|
CREATE MATERIALIZED VIEW matview_102 AS SELECT * from loc_tb JOIN v103 USING (a);
|
||||||
CREATE OR REPLACE VIEW v103 AS SELECT * from loc_tb JOIN matview_102 USING (a);
|
CREATE OR REPLACE VIEW v103 AS SELECT * from loc_tb JOIN matview_102 USING (a);
|
||||||
|
|
||||||
|
-- fails to add local table to metadata, because of the circular dependency
|
||||||
|
ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a);
|
||||||
|
-- drop the view&matview with circular dependency
|
||||||
|
DROP VIEW v103 CASCADE;
|
||||||
|
|
||||||
SET client_min_messages TO DEBUG1;
|
SET client_min_messages TO DEBUG1;
|
||||||
-- auto undistribute
|
-- now it should successfully add to metadata and create the views on workers
|
||||||
ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a);
|
ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a);
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
|
|
||||||
-- works fine
|
-- works fine
|
||||||
select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100, citus_local_tables_mx.v101, citus_local_tables_mx.v102$$);
|
select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100, citus_local_tables_mx.v101, citus_local_tables_mx.v102$$);
|
||||||
|
|
||||||
|
-- auto undistribute
|
||||||
ALTER TABLE loc_tb DROP CONSTRAINT fkey;
|
ALTER TABLE loc_tb DROP CONSTRAINT fkey;
|
||||||
-- fails because fkey is dropped and table is converted to local table
|
-- fails because fkey is dropped and table is converted to local table
|
||||||
select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100$$);
|
select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100$$);
|
||||||
|
@ -537,6 +543,19 @@ SELECT count(*) FROM citus_local_tables_mx.mv2;
|
||||||
SELECT count(*) FROM citus_local_tables_mx.mv3;
|
SELECT count(*) FROM citus_local_tables_mx.mv3;
|
||||||
SELECT count(*) FROM citus_local_tables_mx.mv4;
|
SELECT count(*) FROM citus_local_tables_mx.mv4;
|
||||||
|
|
||||||
|
-- test circular dependency detection among views
|
||||||
|
create table root_tbl (a int);
|
||||||
|
create materialized view chain_v1 as select * from root_tbl;
|
||||||
|
create view chain_v2 as select * from chain_v1;
|
||||||
|
create materialized view chain_v3 as select * from chain_v2;
|
||||||
|
create or replace view chain_v2 as select * from chain_v1 join chain_v3 using (a);
|
||||||
|
-- catch circular dependency and error out
|
||||||
|
select citus_add_local_table_to_metadata('root_tbl');
|
||||||
|
-- same for create_distributed_table
|
||||||
|
select create_distributed_table('root_tbl','a');
|
||||||
|
-- fix the circular dependency and add to metadata
|
||||||
|
create or replace view chain_v2 as select * from chain_v1;
|
||||||
|
select citus_add_local_table_to_metadata('root_tbl');
|
||||||
-- todo: add more matview tests once 5968 and 6028 are fixed
|
-- todo: add more matview tests once 5968 and 6028 are fixed
|
||||||
|
|
||||||
-- cleanup at exit
|
-- cleanup at exit
|
||||||
|
|
Loading…
Reference in New Issue