From c8e1e243b8190fee57402900968f74110dfb4512 Mon Sep 17 00:00:00 2001 From: Ahmet Gedemenli Date: Mon, 4 Jul 2022 17:00:07 +0300 Subject: [PATCH] Fix matviews for citus_add_local_table_to_metadata (#6023) --- .../distributed/commands/alter_table.c | 55 ++++++ ..._table_operation_for_connected_relations.c | 19 +- .../citus_add_local_table_to_metadata.c | 6 +- src/backend/distributed/shared_library_init.c | 11 ++ src/include/distributed/commands.h | 3 +- src/include/distributed/metadata_utility.h | 1 + .../alter_table_set_access_method.out | 2 +- .../expected/citus_local_tables_mx.out | 168 ++++++++++++++++++ .../regress/sql/citus_local_tables_mx.sql | 75 ++++++++ 9 files changed, 331 insertions(+), 9 deletions(-) diff --git a/src/backend/distributed/commands/alter_table.c b/src/backend/distributed/commands/alter_table.c index d6791c9ee..f5c5d67bb 100644 --- a/src/backend/distributed/commands/alter_table.c +++ b/src/backend/distributed/commands/alter_table.c @@ -207,6 +207,7 @@ static char * CreateWorkerChangeSequenceDependencyCommand(char *sequenceSchemaNa char *sourceName, char *targetSchemaName, char *targetName); +static void ErrorIfMatViewSizeExceedsTheLimit(Oid matViewOid); static char * CreateMaterializedViewDDLCommand(Oid matViewOid); static char * GetAccessMethodForMatViewIfExists(Oid viewOid); static bool WillRecreateForeignKeyToReferenceTable(Oid relationId, @@ -223,6 +224,8 @@ PG_FUNCTION_INFO_V1(worker_change_sequence_dependency); /* global variable keeping track of whether we are in a table type conversion function */ bool InTableTypeConversionFunctionCall = false; +/* controlled by GUC, in MB */ +int MaxMatViewSizeToAutoRecreate = 1024; /* * undistribute_table gets a distributed table name and @@ -1357,6 +1360,7 @@ List * GetViewCreationCommandsOfTable(Oid relationId) { List *views = GetDependingViews(relationId); + List *commands = NIL; Oid viewOid = InvalidOid; @@ -1367,6 +1371,8 @@ GetViewCreationCommandsOfTable(Oid relationId) /* See comments on CreateMaterializedViewDDLCommand for its limitations */ if (get_rel_relkind(viewOid) == RELKIND_MATVIEW) { + ErrorIfMatViewSizeExceedsTheLimit(viewOid); + char *matViewCreateCommands = CreateMaterializedViewDDLCommand(viewOid); appendStringInfoString(query, matViewCreateCommands); } @@ -1406,6 +1412,42 @@ GetViewCreationTableDDLCommandsOfTable(Oid relationId) } +/* + * ErrorIfMatViewSizeExceedsTheLimit takes the oid of a materialized view and errors + * out if the size of the matview exceeds the limit set by the GUC + * citus.max_matview_size_to_auto_recreate. + */ +static void +ErrorIfMatViewSizeExceedsTheLimit(Oid matViewOid) +{ + if (MaxMatViewSizeToAutoRecreate >= 0) + { + /* if it's below 0, it means the user has removed the limit */ + Datum relSizeDatum = DirectFunctionCall1(pg_total_relation_size, + ObjectIdGetDatum(matViewOid)); + uint64 matViewSize = DatumGetInt64(relSizeDatum); + + /* convert from MB to bytes */ + uint64 limitSizeInBytes = MaxMatViewSizeToAutoRecreate * 1024L * 1024L; + + if (matViewSize > limitSizeInBytes) + { + ereport(ERROR, (errmsg("size of the materialized view %s exceeds " + "citus.max_matview_size_to_auto_recreate " + "(currently %d MB)", get_rel_name(matViewOid), + MaxMatViewSizeToAutoRecreate), + errdetail("Citus restricts automatically recreating " + "materialized views that are larger than the " + "limit, because it could take too long."), + errhint( + "Consider increasing the size limit by setting " + "citus.max_matview_size_to_auto_recreate; " + "or you can remove the limit by setting it to -1"))); + } + } +} + + /* * CreateMaterializedViewDDLCommand creates the command to create materialized view. * Note that this function doesn't support @@ -1967,6 +2009,19 @@ ExecuteQueryViaSPI(char *query, int SPIOK) } +/* + * ExecuteAndLogQueryViaSPI is a wrapper around ExecuteQueryViaSPI, that logs + * the query to be executed, with the given log level. + */ +void +ExecuteAndLogQueryViaSPI(char *query, int SPIOK, int logLevel) +{ + ereport(logLevel, (errmsg("executing \"%s\"", query))); + + ExecuteQueryViaSPI(query, SPIOK); +} + + /* * SwitchToSequentialAndLocalExecutionIfRelationNameTooLong generates the longest shard name * on the shards of a distributed table, and if exceeds the limit switches to sequential and diff --git a/src/backend/distributed/commands/cascade_table_operation_for_connected_relations.c b/src/backend/distributed/commands/cascade_table_operation_for_connected_relations.c index a31fd3cc1..5b22ecbab 100644 --- a/src/backend/distributed/commands/cascade_table_operation_for_connected_relations.c +++ b/src/backend/distributed/commands/cascade_table_operation_for_connected_relations.c @@ -26,6 +26,7 @@ #include "distributed/reference_table_utils.h" #include "distributed/relation_access_tracking.h" #include "distributed/worker_protocol.h" +#include "executor/spi.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -513,12 +514,12 @@ ExecuteCascadeOperationForRelationIdList(List *relationIdList, /* - * ExecuteAndLogUtilityCommandListInTableTypeConversion is a wrapper function - * around ExecuteAndLogUtilityCommandList, that makes it execute with the flag - * InTableTypeConversionFunctionCall is set to true. + * ExecuteAndLogUtilityCommandListInTableTypeConversionViaSPI is a wrapper function + * around ExecuteAndLogQueryViaSPI, that executes view creation commands + * with the flag InTableTypeConversionFunctionCall set to true. */ void -ExecuteAndLogUtilityCommandListInTableTypeConversion(List *utilityCommandList) +ExecuteAndLogUtilityCommandListInTableTypeConversionViaSPI(List *utilityCommandList) { bool oldValue = InTableTypeConversionFunctionCall; InTableTypeConversionFunctionCall = true; @@ -526,7 +527,15 @@ ExecuteAndLogUtilityCommandListInTableTypeConversion(List *utilityCommandList) MemoryContext savedMemoryContext = CurrentMemoryContext; PG_TRY(); { - ExecuteAndLogUtilityCommandList(utilityCommandList); + char *utilityCommand = NULL; + foreach_ptr(utilityCommand, utilityCommandList) + { + /* + * CREATE MATERIALIZED VIEW commands need to be parsed/transformed, + * which SPI does for us. + */ + ExecuteAndLogQueryViaSPI(utilityCommand, SPI_OK_UTILITY, DEBUG1); + } } PG_CATCH(); { diff --git a/src/backend/distributed/commands/citus_add_local_table_to_metadata.c b/src/backend/distributed/commands/citus_add_local_table_to_metadata.c index d9335fcbc..e85d07c0b 100644 --- a/src/backend/distributed/commands/citus_add_local_table_to_metadata.c +++ b/src/backend/distributed/commands/citus_add_local_table_to_metadata.c @@ -349,7 +349,7 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys, bool autoConve * Execute the view creation commands with the shell table. * Views will be distributed via FinalizeCitusLocalTableCreation below. */ - ExecuteAndLogUtilityCommandListInTableTypeConversion(tableViewCreationCommands); + ExecuteAndLogUtilityCommandListInTableTypeConversionViaSPI(tableViewCreationCommands); /* * Set shellRelationId as the relation with relationId now points @@ -1053,7 +1053,9 @@ DropViewsOnTable(Oid relationId) char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); StringInfo dropCommand = makeStringInfo(); - appendStringInfo(dropCommand, "DROP VIEW IF EXISTS %s", + appendStringInfo(dropCommand, "DROP %sVIEW IF EXISTS %s", + get_rel_relkind(viewId) == RELKIND_MATVIEW ? "MATERIALIZED " : + "", qualifiedViewName); ExecuteAndLogUtilityCommand(dropCommand->data); diff --git a/src/backend/distributed/shared_library_init.c b/src/backend/distributed/shared_library_init.c index ad479fe32..7af1adfa3 100644 --- a/src/backend/distributed/shared_library_init.c +++ b/src/backend/distributed/shared_library_init.c @@ -1460,6 +1460,17 @@ RegisterCitusConfigVariables(void) GUC_UNIT_KB | GUC_STANDARD, NULL, NULL, NULL); + DefineCustomIntVariable( + "citus.max_matview_size_to_auto_recreate", + gettext_noop("Sets the maximum size of materialized views in MB to " + "automatically distribute them."), + NULL, + &MaxMatViewSizeToAutoRecreate, + 1024, -1, INT_MAX, + PGC_USERSET, + GUC_UNIT_MB | GUC_STANDARD, + NULL, NULL, NULL); + DefineCustomIntVariable( "citus.max_rebalancer_logged_ignored_moves", gettext_noop("Sets the maximum number of ignored moves the rebalance logs"), diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 96172bad4..ad5c4eb5d 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -29,6 +29,7 @@ extern bool EnableLocalReferenceForeignKeys; extern bool EnableUnsafeTriggers; +extern int MaxMatViewSizeToAutoRecreate; extern void SwitchToSequentialAndLocalExecutionIfRelationNameTooLong(Oid relationId, char * @@ -642,7 +643,7 @@ extern bool RelationIdListHasReferenceTable(List *relationIdList); extern List * GetFKeyCreationCommandsForRelationIdList(List *relationIdList); extern void DropRelationForeignKeys(Oid relationId, int flags); extern void SetLocalEnableLocalReferenceForeignKeys(bool state); -extern void ExecuteAndLogUtilityCommandListInTableTypeConversion( +extern void ExecuteAndLogUtilityCommandListInTableTypeConversionViaSPI( List *utilityCommandList); extern void ExecuteAndLogUtilityCommandList(List *ddlCommandList); extern void ExecuteAndLogUtilityCommand(const char *commandString); diff --git a/src/include/distributed/metadata_utility.h b/src/include/distributed/metadata_utility.h index 4e48b5cc0..e5b0877d7 100644 --- a/src/include/distributed/metadata_utility.h +++ b/src/include/distributed/metadata_utility.h @@ -305,6 +305,7 @@ extern bool GetNodeDiskSpaceStatsForConnection(MultiConnection *connection, uint64 *availableBytes, uint64 *totalBytes); extern void ExecuteQueryViaSPI(char *query, int SPIOK); +extern void ExecuteAndLogQueryViaSPI(char *query, int SPIOK, int logLevel); extern void EnsureSequenceTypeSupported(Oid seqOid, Oid attributeTypeId, Oid ownerRelationId); extern void AlterSequenceType(Oid seqOid, Oid typeOid); diff --git a/src/test/regress/expected/alter_table_set_access_method.out b/src/test/regress/expected/alter_table_set_access_method.out index da6cbd868..7165877d5 100644 --- a/src/test/regress/expected/alter_table_set_access_method.out +++ b/src/test/regress/expected/alter_table_set_access_method.out @@ -522,7 +522,7 @@ SELECT table_name, citus_table_type, distribution_column, shard_count, access_me (2 rows) SELECT c.relname, a.amname FROM pg_class c, pg_am a where c.relname SIMILAR TO 'table_type\D*' AND c.relnamespace = 'alter_table_set_access_method'::regnamespace AND c.relam = a.oid; - relname | amname + relname | amname --------------------------------------------------------------------- table_type_citus_local | columnar table_type_dist | columnar diff --git a/src/test/regress/expected/citus_local_tables_mx.out b/src/test/regress/expected/citus_local_tables_mx.out index d8effc8c6..8d7a3fd39 100644 --- a/src/test/regress/expected/citus_local_tables_mx.out +++ b/src/test/regress/expected/citus_local_tables_mx.out @@ -876,7 +876,29 @@ CREATE TABLE loc_tb (a int ); CREATE VIEW v100 AS SELECT * FROM loc_tb; CREATE VIEW v101 AS SELECT * FROM loc_tb JOIN ref_tb USING (a); CREATE VIEW v102 AS SELECT * FROM v101; +-- a regular matview that depends on local table +CREATE MATERIALIZED VIEW matview_101 AS SELECT * from loc_tb; +-- a matview and a view that depend on the local table + each other +CREATE VIEW v103 AS SELECT * from loc_tb; +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); +SET client_min_messages TO DEBUG1; +-- auto undistribute 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 + FROM citus_local_tables_mx.loc_tb; ALTER VIEW citus_local_tables_mx.v100 OWNER TO postgres" +DEBUG: "view v100" has dependency to "table loc_tb" that is not in Citus' metadata +DEBUG: executing "CREATE OR REPLACE VIEW citus_local_tables_mx.v101 (a) AS SELECT loc_tb.a + FROM (citus_local_tables_mx.loc_tb + JOIN citus_local_tables_mx.ref_tb USING (a)); ALTER VIEW citus_local_tables_mx.v101 OWNER TO postgres" +DEBUG: "view v101" has dependency to "table loc_tb" that is not in Citus' metadata +DEBUG: executing "CREATE MATERIALIZED VIEW citus_local_tables_mx.matview_101 USING heap AS SELECT loc_tb.a + FROM citus_local_tables_mx.loc_tb;ALTER MATERIALIZED VIEW citus_local_tables_mx.matview_101 OWNER TO postgres" +DEBUG: executing "CREATE OR REPLACE VIEW citus_local_tables_mx.v102 (a) AS SELECT v101.a + FROM citus_local_tables_mx.v101; ALTER VIEW citus_local_tables_mx.v102 OWNER TO postgres" +DEBUG: "view v102" has dependency to "table loc_tb" that is not in Citus' metadata +DEBUG: validating foreign key constraint "fkey_xxxxxxx" +SET client_min_messages TO WARNING; -- 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$$); run_command_on_workers @@ -908,6 +930,152 @@ select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v100$ (localhost,57638,f,"ERROR: relation ""citus_local_tables_mx.v102"" does not exist") (2 rows) +INSERT INTO loc_tb VALUES (1), (2); +-- test a matview with columnar +CREATE MATERIALIZED VIEW matview_columnar USING COLUMNAR AS SELECT * FROM loc_tb WITH DATA; +-- cant recreate matviews, because the size limit is set to zero, by the GUC +SET citus.max_matview_size_to_auto_recreate TO 0; +SELECT citus_add_local_table_to_metadata('loc_tb', true); +ERROR: size of the materialized view matview_columnar exceeds citus.max_matview_size_to_auto_recreate (currently 0 MB) +-- remove the limit +SET citus.max_matview_size_to_auto_recreate TO -1; +SELECT citus_add_local_table_to_metadata('loc_tb', true); + citus_add_local_table_to_metadata +--------------------------------------------------------------------- + +(1 row) + +-- test REFRESH MAT VIEW +SELECT * FROM matview_101 ORDER BY a; + a +--------------------------------------------------------------------- +(0 rows) + +REFRESH MATERIALIZED VIEW matview_101; +SELECT * FROM matview_101 ORDER BY a; + a +--------------------------------------------------------------------- + 1 + 2 +(2 rows) + +-- verify columnar matview works on a table added to metadata +SELECT * FROM matview_columnar; + a +--------------------------------------------------------------------- +(0 rows) + +REFRESH MATERIALIZED VIEW matview_columnar; +SELECT * FROM matview_columnar ORDER BY a; + a +--------------------------------------------------------------------- + 1 + 2 +(2 rows) + +-- test with partitioned tables +SET citus.use_citus_managed_tables TO ON; +CREATE TABLE parent_1 (a INT UNIQUE) PARTITION BY RANGE(a); +SET citus.use_citus_managed_tables TO OFF; +CREATE MATERIALIZED VIEW part_matview1 as SELECT count(*) FROM parent_1 JOIN parent_1 p2 ON (true); +CREATE MATERIALIZED VIEW part_matview2 as SELECT count(*) FROM parent_1 JOIN part_matview1 on (true); +SELECT count(*) FROM citus_local_tables_mx.part_matview1 JOIN citus_local_tables_mx.part_matview2 ON (true); + count +--------------------------------------------------------------------- + 1 +(1 row) + +CREATE TABLE parent_1_child_1 (a int); +CREATE TABLE parent_1_child_2 (a int); +-- create matviews on partition tables +CREATE MATERIALIZED VIEW mv1 AS SELECT * FROM parent_1_child_1; +CREATE MATERIALIZED VIEW mv2 AS SELECT * FROM parent_1_child_2; +CREATE MATERIALIZED VIEW mv3 AS SELECT parent_1_child_2.* FROM parent_1_child_2 JOIN parent_1_child_1 USING(a); +CREATE MATERIALIZED VIEW mv4 AS SELECT * FROM mv3; +alter table parent_1 attach partition parent_1_child_1 FOR VALUES FROM (0) TO (10) ; +-- all matviews work +SELECT count(*) FROM citus_local_tables_mx.mv1; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv2; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv3; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv4; + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- recreate matviews and verify they still work +alter table parent_1 attach partition parent_1_child_2 FOR VALUES FROM (10) TO (20); +SELECT count(*) FROM citus_local_tables_mx.mv1; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv2; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv3; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv4; + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- verify matviews work after undistributing +SELECT undistribute_table('parent_1'); + undistribute_table +--------------------------------------------------------------------- + +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv1; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv2; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv3; + count +--------------------------------------------------------------------- + 0 +(1 row) + +SELECT count(*) FROM citus_local_tables_mx.mv4; + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- todo: add more matview tests once 5968 and 6028 are fixed -- cleanup at exit set client_min_messages to error; DROP SCHEMA citus_local_tables_mx CASCADE; diff --git a/src/test/regress/sql/citus_local_tables_mx.sql b/src/test/regress/sql/citus_local_tables_mx.sql index ac3f6e4d4..c81cac2e6 100644 --- a/src/test/regress/sql/citus_local_tables_mx.sql +++ b/src/test/regress/sql/citus_local_tables_mx.sql @@ -453,7 +453,17 @@ CREATE VIEW v100 AS SELECT * FROM loc_tb; CREATE VIEW v101 AS SELECT * FROM loc_tb JOIN ref_tb USING (a); CREATE VIEW v102 AS SELECT * FROM v101; +-- a regular matview that depends on local table +CREATE MATERIALIZED VIEW matview_101 AS SELECT * from loc_tb; +-- a matview and a view that depend on the local table + each other +CREATE VIEW v103 AS SELECT * from loc_tb; +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); + +SET client_min_messages TO DEBUG1; +-- auto undistribute ALTER TABLE loc_tb ADD CONSTRAINT fkey FOREIGN KEY (a) references ref_tb(a); +SET client_min_messages TO WARNING; -- 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$$); @@ -464,6 +474,71 @@ 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.v101$$); select run_command_on_workers($$SELECT count(*) from citus_local_tables_mx.v102$$); +INSERT INTO loc_tb VALUES (1), (2); +-- test a matview with columnar +CREATE MATERIALIZED VIEW matview_columnar USING COLUMNAR AS SELECT * FROM loc_tb WITH DATA; + +-- cant recreate matviews, because the size limit is set to zero, by the GUC +SET citus.max_matview_size_to_auto_recreate TO 0; +SELECT citus_add_local_table_to_metadata('loc_tb', true); +-- remove the limit +SET citus.max_matview_size_to_auto_recreate TO -1; +SELECT citus_add_local_table_to_metadata('loc_tb', true); + +-- test REFRESH MAT VIEW +SELECT * FROM matview_101 ORDER BY a; +REFRESH MATERIALIZED VIEW matview_101; +SELECT * FROM matview_101 ORDER BY a; + +-- verify columnar matview works on a table added to metadata +SELECT * FROM matview_columnar; +REFRESH MATERIALIZED VIEW matview_columnar; +SELECT * FROM matview_columnar ORDER BY a; + +-- test with partitioned tables +SET citus.use_citus_managed_tables TO ON; +CREATE TABLE parent_1 (a INT UNIQUE) PARTITION BY RANGE(a); +SET citus.use_citus_managed_tables TO OFF; + +CREATE MATERIALIZED VIEW part_matview1 as SELECT count(*) FROM parent_1 JOIN parent_1 p2 ON (true); +CREATE MATERIALIZED VIEW part_matview2 as SELECT count(*) FROM parent_1 JOIN part_matview1 on (true); + +SELECT count(*) FROM citus_local_tables_mx.part_matview1 JOIN citus_local_tables_mx.part_matview2 ON (true); + +CREATE TABLE parent_1_child_1 (a int); +CREATE TABLE parent_1_child_2 (a int); + +-- create matviews on partition tables +CREATE MATERIALIZED VIEW mv1 AS SELECT * FROM parent_1_child_1; +CREATE MATERIALIZED VIEW mv2 AS SELECT * FROM parent_1_child_2; +CREATE MATERIALIZED VIEW mv3 AS SELECT parent_1_child_2.* FROM parent_1_child_2 JOIN parent_1_child_1 USING(a); +CREATE MATERIALIZED VIEW mv4 AS SELECT * FROM mv3; + +alter table parent_1 attach partition parent_1_child_1 FOR VALUES FROM (0) TO (10) ; + +-- all matviews work +SELECT count(*) FROM citus_local_tables_mx.mv1; +SELECT count(*) FROM citus_local_tables_mx.mv2; +SELECT count(*) FROM citus_local_tables_mx.mv3; +SELECT count(*) FROM citus_local_tables_mx.mv4; + +-- recreate matviews and verify they still work +alter table parent_1 attach partition parent_1_child_2 FOR VALUES FROM (10) TO (20); + +SELECT count(*) FROM citus_local_tables_mx.mv1; +SELECT count(*) FROM citus_local_tables_mx.mv2; +SELECT count(*) FROM citus_local_tables_mx.mv3; +SELECT count(*) FROM citus_local_tables_mx.mv4; + +-- verify matviews work after undistributing +SELECT undistribute_table('parent_1'); +SELECT count(*) FROM citus_local_tables_mx.mv1; +SELECT count(*) FROM citus_local_tables_mx.mv2; +SELECT count(*) FROM citus_local_tables_mx.mv3; +SELECT count(*) FROM citus_local_tables_mx.mv4; + +-- todo: add more matview tests once 5968 and 6028 are fixed + -- cleanup at exit set client_min_messages to error; DROP SCHEMA citus_local_tables_mx CASCADE;