From a5e09ffa2a269167a87a2c81c202b2f360d849bf Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Tue, 29 Jun 2021 13:36:01 +0200 Subject: [PATCH] very wip --- .../distributed/commands/alter_table.c | 68 +++++++++++-------- .../distributed/commands/dependencies.c | 62 ++++++++++++++++- src/backend/distributed/metadata/dependency.c | 6 +- src/include/distributed/metadata_utility.h | 2 +- 4 files changed, 106 insertions(+), 32 deletions(-) diff --git a/src/backend/distributed/commands/alter_table.c b/src/backend/distributed/commands/alter_table.c index da2e5490c..9b150f173 100644 --- a/src/backend/distributed/commands/alter_table.c +++ b/src/backend/distributed/commands/alter_table.c @@ -1120,41 +1120,51 @@ GetViewCreationCommandsOfTable(Oid relationId) Oid viewOid = InvalidOid; foreach_oid(viewOid, views) { - Datum viewDefinitionDatum = DirectFunctionCall1(pg_get_viewdef, - ObjectIdGetDatum(viewOid)); - char *viewDefinition = TextDatumGetCString(viewDefinitionDatum); - StringInfo query = makeStringInfo(); - char *viewName = get_rel_name(viewOid); - char *schemaName = get_namespace_name(get_rel_namespace(viewOid)); - char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); - bool isMatView = get_rel_relkind(viewOid) == RELKIND_MATVIEW; - - /* 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)); + commands = lappend(commands, makeTableDDLCommandString(GetViewCreationCommand( + viewOid))); } return commands; } +char * +GetViewCreationCommand(Oid viewOid) +{ + Datum viewDefinitionDatum = DirectFunctionCall1(pg_get_viewdef, + ObjectIdGetDatum(viewOid)); + char *viewDefinition = TextDatumGetCString(viewDefinitionDatum); + StringInfo query = makeStringInfo(); + char *viewName = get_rel_name(viewOid); + char *schemaName = get_namespace_name(get_rel_namespace(viewOid)); + char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); + bool isMatView = get_rel_relkind(viewOid) == RELKIND_MATVIEW; + + /* here we need to get the access method of the view to recreate it */ + char *accessMethodName = GetAccessMethodForMatViewIfExists(viewOid); + + appendStringInfo(query, "DROP VIEW IF EXISTS %s CASCADE;", qualifiedViewName); + + 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); + + return query->data; +} + + /* * ReplaceTable replaces the source table with the target table. * It moves all the rows of the source table to target table with INSERT SELECT. diff --git a/src/backend/distributed/commands/dependencies.c b/src/backend/distributed/commands/dependencies.c index 60cb56492..9d047723b 100644 --- a/src/backend/distributed/commands/dependencies.c +++ b/src/backend/distributed/commands/dependencies.c @@ -69,6 +69,43 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target) dependenciesWithCommands = lappend(dependenciesWithCommands, dependency); } } + + List *metadataSyncedDependenciesWithCommands = NIL; + + if (target->classId == RelationRelationId) + { + /* don't forget partitioned/foreign tables */ + if (get_rel_relkind(target->objectId) == RELKIND_RELATION) + { + List *viewIds = GetDependingViews(target->objectId); + Oid viewOid = InvalidOid; + foreach_oid(viewOid, viewIds) + { + ObjectAddress viewAddress = { 0 }; + ObjectAddressSet(viewAddress, RelationRelationId, viewOid); + + dependencies = GetDependenciesForObject(&viewAddress); + foreach_ptr(dependency, dependencies) + { + List *dependencyCommands = GetDependencyCreateDDLCommands(dependency); + metadataSyncedDependenciesWithCommands = list_concat( + metadataSyncedDependenciesWithCommands, dependencyCommands); + + char *viewDefinition = GetViewCreationCommand(viewOid); + metadataSyncedDependenciesWithCommands = lappend( + metadataSyncedDependenciesWithCommands, viewDefinition); + + /* create a new list with dependencies that actually created commands */ + if (list_length(dependencyCommands) > 0) + { + metadataSyncedDependenciesWithCommands = lappend( + metadataSyncedDependenciesWithCommands, dependency); + } + } + } + } + } + if (list_length(ddlCommands) <= 0) { /* no ddl commands to be executed */ @@ -77,6 +114,9 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target) /* since we are executing ddl commands lets disable propagation, primarily for mx */ ddlCommands = list_concat(list_make1(DISABLE_DDL_PROPAGATION), ddlCommands); + metadataSyncedDependenciesWithCommands = list_concat(list_make1( + DISABLE_DDL_PROPAGATION), + metadataSyncedDependenciesWithCommands); /* * Make sure that no new nodes are added after this point until the end of the @@ -112,7 +152,6 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target) return; } - WorkerNode *workerNode = NULL; foreach_ptr(workerNode, workerNodeList) { @@ -123,6 +162,20 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target) CitusExtensionOwnerName(), ddlCommands); } + + + foreach_ptr(workerNode, workerNodeList) + { + const char *nodeName = workerNode->workerName; + uint32 nodePort = workerNode->workerPort; + + if (workerNode->hasMetadata) + { + SendCommandListToWorkerInSingleTransaction(nodeName, nodePort, + CitusExtensionOwnerName(), + metadataSyncedDependenciesWithCommands); + } + } } @@ -182,6 +235,13 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency) { return NIL; } + else if (get_rel_relkind(dependency->objectId) == RELKIND_VIEW || + get_rel_relkind(dependency->objectId) == RELKIND_MATVIEW) + { + char *viewDef = GetViewCreationCommand(dependency->objectId); + + return list_make1(viewDef); + } /* if this relation is not supported, break to the error at the end */ break; diff --git a/src/backend/distributed/metadata/dependency.c b/src/backend/distributed/metadata/dependency.c index 6dfa6afce..232302df4 100644 --- a/src/backend/distributed/metadata/dependency.c +++ b/src/backend/distributed/metadata/dependency.c @@ -648,7 +648,11 @@ SupportedDependencyByCitus(const ObjectAddress *address) { return true; } - + else if (get_rel_relkind(address->objectId) == RELKIND_VIEW || + get_rel_relkind(address->objectId) == RELKIND_MATVIEW) + { + return true; + } return false; } diff --git a/src/include/distributed/metadata_utility.h b/src/include/distributed/metadata_utility.h index 76f3dd65e..5b89d98fb 100644 --- a/src/include/distributed/metadata_utility.h +++ b/src/include/distributed/metadata_utility.h @@ -248,7 +248,7 @@ extern void CreateDistributedTable(Oid relationId, Var *distributionColumn, bool viaDeprecatedAPI); extern void CreateTruncateTrigger(Oid relationId); extern TableConversionReturn * UndistributeTable(TableConversionParameters *params); - +extern char * GetViewCreationCommand(Oid viewOid); extern void EnsureDependenciesExistOnAllNodes(const ObjectAddress *target); extern List * GetDistributableDependenciesForObject(const ObjectAddress *target); extern bool ShouldPropagate(void);