diff --git a/src/backend/distributed/commands/alter_table.c b/src/backend/distributed/commands/alter_table.c index 0bfc1b2a1..ddc62021a 100644 --- a/src/backend/distributed/commands/alter_table.c +++ b/src/backend/distributed/commands/alter_table.c @@ -34,6 +34,7 @@ #include "catalog/pg_am.h" #include "columnar/columnar.h" #include "columnar/columnar_tableam.h" +#include "commands/defrem.h" #include "distributed/colocation_utils.h" #include "distributed/commands.h" #include "distributed/commands/utility_hook.h" @@ -199,6 +200,7 @@ static char * CreateWorkerChangeSequenceDependencyCommand(char *sequenceSchemaNa char *sourceName, char *targetSchemaName, char *targetName); +static char * GetAccessMethodForMatViewIfExists(Oid viewOid); static bool WillRecreateForeignKeyToReferenceTable(Oid relationId, CascadeToColocatedOption cascadeOption); static void WarningsForDroppingForeignKeysWithDistributedTables(Oid relationId); @@ -1126,13 +1128,28 @@ GetViewCreationCommandsOfTable(Oid relationId) char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); bool isMatView = get_rel_relkind(viewOid) == RELKIND_MATVIEW; - appendStringInfo(query, - "CREATE %s VIEW %s AS %s", - isMatView ? "MATERIALIZED" : "", - qualifiedViewName, - viewDefinition); + /* here we need to get the access method of the view to recreate it */ + char *accessMethodName = GetAccessMethodForMatViewIfExists(viewOid); + + appendStringInfoString(query, "CREATE "); + + if (isMatView) + { + appendStringInfoString(query, "MATERIALIZED "); + } + + appendStringInfo(query, "VIEW %s ", qualifiedViewName); + + if (accessMethodName) + { + appendStringInfo(query, "USING %s ", accessMethodName); + } + + appendStringInfo(query, "AS %s", viewDefinition); + commands = lappend(commands, makeTableDDLCommandString(query->data)); } + return commands; } @@ -1517,6 +1534,32 @@ CreateWorkerChangeSequenceDependencyCommand(char *sequenceSchemaName, char *sequ } +/* + * GetAccessMethodForMatViewIfExists returns if there's an access method + * set to the view with the given oid. Returns NULL otherwise. + */ +static char * +GetAccessMethodForMatViewIfExists(Oid viewOid) +{ + char *accessMethodName = NULL; + Relation relation = try_relation_open(viewOid, AccessShareLock); + if (relation == NULL) + { + ereport(ERROR, (errmsg("cannot complete operation " + "because no such view exists"))); + } + + Oid accessMethodOid = relation->rd_rel->relam; + if (OidIsValid(accessMethodOid)) + { + accessMethodName = get_am_name(accessMethodOid); + } + relation_close(relation, NoLock); + + return accessMethodName; +} + + /* * WillRecreateForeignKeyToReferenceTable checks if the table of relationId has any foreign * key to a reference table, if conversion will be cascaded to colocated table this function diff --git a/src/test/regress/expected/alter_distributed_table.out b/src/test/regress/expected/alter_distributed_table.out index fc09bba76..edc640f58 100644 --- a/src/test/regress/expected/alter_distributed_table.out +++ b/src/test/regress/expected/alter_distributed_table.out @@ -917,5 +917,32 @@ NOTICE: renaming the new table to alter_distributed_table.partition_lengths_123 (1 row) +-- verify that alter_distributed_table doesn't change the access methods for the views on the table +CREATE TABLE test_am_matview(a int); +SELECT create_distributed_table('test_am_matview' ,'a', colocate_with:='none'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CREATE MATERIALIZED VIEW test_mat_view_am USING COLUMNAR AS SELECT count(*), a FROM test_am_matview GROUP BY a ; +SELECT alter_distributed_table('test_am_matview', shard_count:= 52); +NOTICE: creating a new table for alter_distributed_table.test_am_matview +NOTICE: moving the data of alter_distributed_table.test_am_matview +NOTICE: dropping the old alter_distributed_table.test_am_matview +NOTICE: drop cascades to materialized view test_mat_view_am +CONTEXT: SQL statement "DROP TABLE alter_distributed_table.test_am_matview CASCADE" +NOTICE: renaming the new table to alter_distributed_table.test_am_matview + alter_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT amname FROM pg_am WHERE oid IN (SELECT relam FROM pg_class WHERE relname ='test_mat_view_am'); + amname +--------------------------------------------------------------------- + columnar +(1 row) + SET client_min_messages TO WARNING; DROP SCHEMA alter_distributed_table CASCADE; diff --git a/src/test/regress/sql/alter_distributed_table.sql b/src/test/regress/sql/alter_distributed_table.sql index 8c6d76527..5357695fd 100644 --- a/src/test/regress/sql/alter_distributed_table.sql +++ b/src/test/regress/sql/alter_distributed_table.sql @@ -308,5 +308,12 @@ ALTER TABLE partition_lengths RENAME TO partition_lengths_1234567890123456789012 -- verify alter_distributed_table works with long partitioned table names SELECT alter_distributed_table('partition_lengths_12345678901234567890123456789012345678901234567890', shard_count := 17, cascade_to_colocated := false); +-- verify that alter_distributed_table doesn't change the access methods for the views on the table +CREATE TABLE test_am_matview(a int); +SELECT create_distributed_table('test_am_matview' ,'a', colocate_with:='none'); +CREATE MATERIALIZED VIEW test_mat_view_am USING COLUMNAR AS SELECT count(*), a FROM test_am_matview GROUP BY a ; +SELECT alter_distributed_table('test_am_matview', shard_count:= 52); +SELECT amname FROM pg_am WHERE oid IN (SELECT relam FROM pg_class WHERE relname ='test_mat_view_am'); + SET client_min_messages TO WARNING; DROP SCHEMA alter_distributed_table CASCADE;