Merge branch 'drop_db_as_role' into create_alter_database

pull/7240/head
gindibay 2023-10-24 14:13:48 +03:00
commit 87f694ec0f
9 changed files with 94 additions and 77 deletions

View File

@ -28,6 +28,8 @@
#include "distributed/metadata/distobject.h" #include "distributed/metadata/distobject.h"
#include "distributed/multi_executor.h" #include "distributed/multi_executor.h"
#include "distributed/worker_transaction.h" #include "distributed/worker_transaction.h"
#include "catalog/pg_database.h"
#include "commands/dbcommands.h"
/* /*
@ -339,3 +341,4 @@ DropTextSearchConfigObjectAddress(Node *node, bool missing_ok, bool isPostproces
return objectAddresses; return objectAddresses;
} }

View File

@ -273,16 +273,11 @@ PostprocessCreateDatabaseStmt(Node *node, const char *queryString)
char *createDatabaseCommand = DeparseTreeNode(node); char *createDatabaseCommand = DeparseTreeNode(node);
StringInfo internalCreateCommand = makeStringInfo();
appendStringInfo(internalCreateCommand,
"SELECT pg_catalog.citus_internal_database_command(%s)",
quote_literal_cstr(createDatabaseCommand));
List *commands = list_make3(DISABLE_DDL_PROPAGATION, List *commands = list_make3(DISABLE_DDL_PROPAGATION,
(void *) internalCreateCommand->data, (void *) createDatabaseCommand,
ENABLE_DDL_PROPAGATION); ENABLE_DDL_PROPAGATION);
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); return NontransactionalNodeDDLTask(NON_COORDINATOR_NODES, commands);
} }
@ -352,37 +347,11 @@ citus_internal_database_command(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
static char *
GetUnmarkDatabaseDistributedSql(char *dbName)
{
StringInfoData pg_dist_object_delete = { 0 };
initStringInfo(&pg_dist_object_delete);
appendStringInfo(&pg_dist_object_delete, "delete from pg_dist_object where "
"objid in (select oid from pg_database where datname = '%s')",
dbName);
return pg_dist_object_delete.data;
}
static void
UnmarkObjectDistributedForDropDb(const ObjectAddress *distAddress, char *dbName)
{
UnmarkObjectDistributed(distAddress);
if (EnableMetadataSync)
{
char *workerPgDistObjectUpdateCommand =
GetUnmarkDatabaseDistributedSql(dbName);
SendCommandToWorkersWithMetadata(workerPgDistObjectUpdateCommand);
}
}
List * List *
PreprocessDropDatabaseStmt(Node *node, const char *queryString, PreprocessDropDatabaseStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext) ProcessUtilityContext processUtilityContext)
{ {
bool isPostProcess = false;
if (!EnableCreateDatabasePropagation || !ShouldPropagate()) if (!EnableCreateDatabasePropagation || !ShouldPropagate())
{ {
return NIL; return NIL;
@ -392,49 +361,49 @@ PreprocessDropDatabaseStmt(Node *node, const char *queryString,
DropdbStmt *stmt = (DropdbStmt *) node; DropdbStmt *stmt = (DropdbStmt *) node;
Oid databaseOid = get_database_oid(stmt->dbname, stmt->missing_ok); List *addresses = GetObjectAddressListFromParseTree(node, stmt->missing_ok, isPostProcess);
if (databaseOid == InvalidOid) if (list_length(addresses) == 0)
{
/* let regular ProcessUtility deal with IF NOT EXISTS */
return NIL;
}
ObjectAddress dbAddress = { 0 };
ObjectAddressSet(dbAddress, DatabaseRelationId, databaseOid);
if (!IsObjectDistributed(&dbAddress))
{ {
return NIL; return NIL;
} }
UnmarkObjectDistributedForDropDb(&dbAddress, stmt->dbname); ObjectAddress *address = (ObjectAddress *) linitial(addresses);
char *unmarkDatabaseDistributedSql = GetUnmarkDatabaseDistributedSql(stmt->dbname); if (address->objectId == InvalidOid ||!IsObjectDistributed(address))
{
return NIL;
}
char *dropDatabaseCommand = DeparseTreeNode(node); char *dropDatabaseCommand = DeparseTreeNode(node);
StringInfo internalDropCommand = makeStringInfo();
appendStringInfo(internalDropCommand,
"SELECT pg_catalog.citus_internal_database_command(%s)",
quote_literal_cstr(dropDatabaseCommand));
List *commands = list_make3(DISABLE_DDL_PROPAGATION,
List *commands = list_make4(DISABLE_DDL_PROPAGATION, (void *) dropDatabaseCommand,
unmarkDatabaseDistributedSql,
(void *) internalDropCommand->data,
ENABLE_DDL_PROPAGATION); ENABLE_DDL_PROPAGATION);
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); return NontransactionalNodeDDLTask(NON_COORDINATOR_NODES, commands);
} }
static ObjectAddress *GetDatabaseAddressFromDatabaseName(char *databaseName)
{
Oid databaseOid = get_database_oid(databaseName, false);
ObjectAddress *dbAddress = palloc0(sizeof(ObjectAddress));
ObjectAddressSet(*dbAddress, DatabaseRelationId, databaseOid);
return dbAddress;
}
List *
DropDatabaseStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
{
DropdbStmt *stmt = castNode(DropdbStmt, node);
ObjectAddress *dbAddress = GetDatabaseAddressFromDatabaseName(stmt->dbname);
return list_make1(dbAddress);
}
List * List *
CreateDatabaseStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess) CreateDatabaseStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
{ {
CreatedbStmt *stmt = castNode(CreatedbStmt, node); CreatedbStmt *stmt = castNode(CreatedbStmt, node);
Oid databaseOid = get_database_oid(stmt->dbname, missing_ok); ObjectAddress *dbAddress = GetDatabaseAddressFromDatabaseName(stmt->dbname);
ObjectAddress *dbAddress = palloc0(sizeof(ObjectAddress));
ObjectAddressSet(*dbAddress, DatabaseRelationId, databaseOid);
return list_make1(dbAddress); return list_make1(dbAddress);
} }

View File

@ -484,7 +484,7 @@ static DistributeObjectOps Database_Drop = {
.postprocess = NULL, .postprocess = NULL,
.objectType = OBJECT_DATABASE, .objectType = OBJECT_DATABASE,
.operationType = DIST_OPS_DROP, .operationType = DIST_OPS_DROP,
.address = NULL, .address = DropDatabaseStmtObjectAddress,
.markDistributed = false, .markDistributed = false,
}; };

View File

@ -65,7 +65,6 @@ static DefElem * makeDefElemBool(char *name, bool value);
static List * GenerateRoleOptionsList(HeapTuple tuple); static List * GenerateRoleOptionsList(HeapTuple tuple);
static List * GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options); static List * GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options);
static List * GenerateGrantRoleStmtsOfRole(Oid roleid); static List * GenerateGrantRoleStmtsOfRole(Oid roleid);
static void EnsureSequentialModeForRoleDDL(void);
static char * GetRoleNameFromDbRoleSetting(HeapTuple tuple, static char * GetRoleNameFromDbRoleSetting(HeapTuple tuple,
TupleDesc DbRoleSettingDescription); TupleDesc DbRoleSettingDescription);
@ -1080,6 +1079,7 @@ UnmarkRolesDistributed(List *roles)
} }
ObjectAddressSet(roleAddress, AuthIdRelationId, roleOid); ObjectAddressSet(roleAddress, AuthIdRelationId, roleOid);
elog(LOG, "Unmarking role %s as distributed", role->rolename);
UnmarkObjectDistributed(&roleAddress); UnmarkObjectDistributed(&roleAddress);
} }
} }
@ -1278,7 +1278,7 @@ CreateRoleStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
* with the role the role needs to be visible on all connections used by the transaction, * with the role the role needs to be visible on all connections used by the transaction,
* meaning we can only use 1 connection per node. * meaning we can only use 1 connection per node.
*/ */
static void void
EnsureSequentialModeForRoleDDL(void) EnsureSequentialModeForRoleDDL(void)
{ {
if (!IsTransactionBlock()) if (!IsTransactionBlock())

View File

@ -80,6 +80,7 @@
#include "utils/inval.h" #include "utils/inval.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "catalog/pg_database.h"
bool EnableDDLPropagation = true; /* ddl propagation is enabled */ bool EnableDDLPropagation = true; /* ddl propagation is enabled */
@ -148,6 +149,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
DestReceiver *dest, DestReceiver *dest,
QueryCompletion *completionTag) QueryCompletion *completionTag)
{ {
elog(LOG, "multi_ProcessUtility called");
if (readOnlyTree) if (readOnlyTree)
{ {
pstmt = copyObject(pstmt); pstmt = copyObject(pstmt);
@ -578,6 +580,8 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
PreprocessLockStatement((LockStmt *) parsetree, context); PreprocessLockStatement((LockStmt *) parsetree, context);
} }
/* /*
* We only process ALTER TABLE ... ATTACH PARTITION commands in the function below * We only process ALTER TABLE ... ATTACH PARTITION commands in the function below
* and distribute the partition if necessary. * and distribute the partition if necessary.
@ -724,22 +728,12 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
} }
/* /*
* Make sure that dropping the role deletes the pg_dist_object entries. There is a * Make sure that dropping the role and database deletes the pg_dist_object entries. There is a
* separate logic for roles, since roles are not included as dropped objects in the * separate logic for roles and database, since roles and database are not included as dropped objects in the
* drop event trigger. To handle it both on worker and coordinator nodes, it is not * drop event trigger. To handle it both on worker and coordinator nodes, it is not
* implemented as a part of process functions but here. * implemented as a part of process functions but here.
*/ */
if (IsA(parsetree, DropRoleStmt)) UnmarkRolesAndDatabaseDistributed(parsetree);
{
DropRoleStmt *stmt = castNode(DropRoleStmt, parsetree);
List *allDropRoles = stmt->roles;
List *distributedDropRoles = FilterDistributedRoles(allDropRoles);
if (list_length(distributedDropRoles) > 0)
{
UnmarkRolesDistributed(distributedDropRoles);
}
}
pstmt->utilityStmt = parsetree; pstmt->utilityStmt = parsetree;
@ -1488,13 +1482,31 @@ DDLTaskList(Oid relationId, const char *commandString)
return taskList; return taskList;
} }
/*
* NontransactionalNodeDDLTask builds a list of tasks to execute a DDL command on a
* given target set of nodes with cannotBeExecutedInTransction is set to make sure
* that list is being executed without a transaction.
*/
List * NontransactionalNodeDDLTask(TargetWorkerSet targets, List *commands ){
List *ddlJobs = NodeDDLTaskList(NON_COORDINATOR_NODES, commands);
DDLJob *ddlJob = NULL;
foreach_ptr(ddlJob, ddlJobs)
{
Task *task = NULL;
foreach_ptr(task, ddlJob->taskList)
{
task->cannotBeExecutedInTransction = true;
}
}
return ddlJobs;
}
/* /*
* NodeDDLTaskList builds a list of tasks to execute a DDL command on a * NodeDDLTaskList builds a list of tasks to execute a DDL command on a
* given target set of nodes. * given target set of nodes.
*/ */
List * List *
NodeDDLTaskList(TargetWorkerSet targets, List *commands) NodeDDLTaskList(TargetWorkerSet targets, List *commands )
{ {
DDLJob *ddlJob = palloc0(sizeof(DDLJob)); DDLJob *ddlJob = palloc0(sizeof(DDLJob));
ddlJob->targetObjectAddress = InvalidObjectAddress; ddlJob->targetObjectAddress = InvalidObjectAddress;

View File

@ -48,6 +48,8 @@
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/regproc.h" #include "utils/regproc.h"
#include "utils/rel.h" #include "utils/rel.h"
#include "catalog/pg_database.h"
#include "commands/dbcommands.h"
static char * CreatePgDistObjectEntryCommand(const ObjectAddress *objectAddress); static char * CreatePgDistObjectEntryCommand(const ObjectAddress *objectAddress);
@ -355,6 +357,31 @@ ExecuteCommandAsSuperuser(char *query, int paramCount, Oid *paramTypes,
return spiStatus; return spiStatus;
} }
void UnmarkRolesAndDatabaseDistributed(Node *node)
{
if (IsA(node, DropRoleStmt))
{
DropRoleStmt *stmt = castNode(DropRoleStmt, node);
List *allDropRoles = stmt->roles;
List *distributedDropRoles = FilterDistributedRoles(allDropRoles);
if (list_length(distributedDropRoles) > 0)
{
UnmarkRolesDistributed(distributedDropRoles);
}
}
else if (IsA(node, DropdbStmt))
{
DropdbStmt *stmt = castNode(DropdbStmt, node);
char *dbName = stmt->dbname;
Oid dbOid = get_database_oid(dbName, stmt->missing_ok);
ObjectAddress *dbAddress = palloc0(sizeof(ObjectAddress));
ObjectAddressSet(*dbAddress, DatabaseRelationId, dbOid);
UnmarkObjectDistributed(dbAddress);
}
}
/* /*
* UnmarkObjectDistributed removes the entry from pg_dist_object that marks this object as * UnmarkObjectDistributed removes the entry from pg_dist_object that marks this object as

View File

@ -240,6 +240,9 @@ extern List * PreprocessAlterDatabaseSetStmt(Node *node, const char *queryString
extern List * PostprocessCreateDatabaseStmt(Node *node, const char *queryString); extern List * PostprocessCreateDatabaseStmt(Node *node, const char *queryString);
extern List * PreprocessDropDatabaseStmt(Node *node, const char *queryString, extern List * PreprocessDropDatabaseStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext); ProcessUtilityContext processUtilityContext);
extern List * DropDatabaseStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess);
extern List * CreateDatabaseStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess);
/* domain.c - forward declarations */ /* domain.c - forward declarations */
extern List * CreateDomainStmtObjectAddress(Node *node, bool missing_ok, bool extern List * CreateDomainStmtObjectAddress(Node *node, bool missing_ok, bool
@ -510,6 +513,7 @@ extern List * RenameRoleStmtObjectAddress(Node *stmt, bool missing_ok, bool
extern void UnmarkRolesDistributed(List *roles); extern void UnmarkRolesDistributed(List *roles);
extern List * FilterDistributedRoles(List *roles); extern List * FilterDistributedRoles(List *roles);
extern void EnsureSequentialModeForRoleDDL(void);
/* schema.c - forward declarations */ /* schema.c - forward declarations */
extern List * PostprocessCreateSchemaStmt(Node *node, const char *queryString); extern List * PostprocessCreateSchemaStmt(Node *node, const char *queryString);

View File

@ -94,6 +94,7 @@ extern void ProcessUtilityParseTree(Node *node, const char *queryString,
extern void MarkInvalidateForeignKeyGraph(void); extern void MarkInvalidateForeignKeyGraph(void);
extern void InvalidateForeignKeyGraphForDDL(void); extern void InvalidateForeignKeyGraphForDDL(void);
extern List * DDLTaskList(Oid relationId, const char *commandString); extern List * DDLTaskList(Oid relationId, const char *commandString);
extern List * NontransactionalNodeDDLTask(TargetWorkerSet targets, List *commands );
extern List * NodeDDLTaskList(TargetWorkerSet targets, List *commands); extern List * NodeDDLTaskList(TargetWorkerSet targets, List *commands);
extern bool AlterTableInProgress(void); extern bool AlterTableInProgress(void);
extern bool DropSchemaOrDBInProgress(void); extern bool DropSchemaOrDBInProgress(void);

View File

@ -27,6 +27,7 @@ extern void MarkObjectDistributed(const ObjectAddress *distAddress);
extern void MarkObjectDistributedViaSuperUser(const ObjectAddress *distAddress); extern void MarkObjectDistributedViaSuperUser(const ObjectAddress *distAddress);
extern void MarkObjectDistributedLocally(const ObjectAddress *distAddress); extern void MarkObjectDistributedLocally(const ObjectAddress *distAddress);
extern void UnmarkObjectDistributed(const ObjectAddress *address); extern void UnmarkObjectDistributed(const ObjectAddress *address);
extern void UnmarkRolesAndDatabaseDistributed(Node *node);
extern bool IsTableOwnedByExtension(Oid relationId); extern bool IsTableOwnedByExtension(Oid relationId);
extern bool ObjectAddressDependsOnExtension(const ObjectAddress *target); extern bool ObjectAddressDependsOnExtension(const ObjectAddress *target);
extern bool IsAnyObjectAddressOwnedByExtension(const List *targets, extern bool IsAnyObjectAddressOwnedByExtension(const List *targets,