mirror of https://github.com/citusdata/citus.git
Merge branch 'main' into alter_database_nonmain2
commit
879ab1821a
|
@ -11,8 +11,10 @@
|
||||||
* commands from non-main databases.
|
* commands from non-main databases.
|
||||||
*
|
*
|
||||||
* To add support for a new command type, one needs to define a new
|
* To add support for a new command type, one needs to define a new
|
||||||
* NonMainDbDistributeObjectOps object and add it to
|
* NonMainDbDistributeObjectOps object within OperationArray. Also, if
|
||||||
* GetNonMainDbDistributeObjectOps.
|
* the command requires marking or unmarking some objects as distributed,
|
||||||
|
* the necessary operations can be implemented in
|
||||||
|
* RunPreprocessNonMainDBCommand and RunPostprocessNonMainDBCommand.
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -42,161 +44,82 @@
|
||||||
"SELECT pg_catalog.citus_unmark_object_distributed(%d, %d, %d, %s)"
|
"SELECT pg_catalog.citus_unmark_object_distributed(%d, %d, %d, %s)"
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structs used to implement getMarkDistributedParams and
|
|
||||||
* getUnmarkDistributedParams callbacks for NonMainDbDistributeObjectOps.
|
|
||||||
*
|
|
||||||
* Main difference between these two is that while
|
|
||||||
* MarkDistributedGloballyParams contains the name of the object, the other
|
|
||||||
* doesn't. This is because, when marking an object -that is created from a
|
|
||||||
* non-main db- as distributed, citus_internal.mark_object_distributed()
|
|
||||||
* cannot find its name since the object is not visible to outer transaction
|
|
||||||
* (or, read as "the transaction in non-main db").
|
|
||||||
*/
|
|
||||||
typedef struct MarkDistributedGloballyParams
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
Oid id;
|
|
||||||
uint16 catalogRelId;
|
|
||||||
} MarkDistributedGloballyParams;
|
|
||||||
|
|
||||||
typedef struct UnmarkDistributedLocallyParams
|
|
||||||
{
|
|
||||||
Oid id;
|
|
||||||
uint16 catalogRelId;
|
|
||||||
} UnmarkDistributedLocallyParams;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NonMainDbDistributeObjectOps contains the necessary callbacks / flags to
|
* NonMainDbDistributeObjectOps contains the necessary callbacks / flags to
|
||||||
* support node-wide object management commands from non-main databases.
|
* support node-wide object management commands from non-main databases.
|
||||||
*
|
*
|
||||||
* getMarkDistributedParams / getUnmarkDistributedParams:
|
|
||||||
* When creating a distributed object, we always have to mark such objects
|
|
||||||
* as "distributed" but while for some object types we can delegate this to
|
|
||||||
* main database, for some others we have to explicitly send a command to
|
|
||||||
* all nodes in this code-path to achieve this. Callers need to implement
|
|
||||||
* getMarkDistributedParams when that is the case.
|
|
||||||
*
|
|
||||||
* Similarly when dropping a distributed object, we always have to unmark
|
|
||||||
* the target object as "distributed" and our utility hook on remote nodes
|
|
||||||
* achieve this via UnmarkNodeWideObjectsDistributed() because the commands
|
|
||||||
* that we send to workers are executed via main db. However for the local
|
|
||||||
* node, this is not the case as we're not in the main db. For this reason,
|
|
||||||
* callers need to implement getUnmarkDistributedParams to unmark an object
|
|
||||||
* for local node as well.
|
|
||||||
*
|
|
||||||
* We don't expect both of these to be NULL at the same time. However, it's
|
|
||||||
* okay if both of these are NULL.
|
|
||||||
*
|
|
||||||
* Finally, while getMarkDistributedParams is expected to return "a list of
|
|
||||||
* objects", this is not the case for getUnmarkDistributedParams. This is
|
|
||||||
* because, while we expect that a drop command might drop multiple objects
|
|
||||||
* at once, we don't expect a create command to create multiple objects at
|
|
||||||
* once.
|
|
||||||
*
|
|
||||||
* cannotBeExecutedInTransaction:
|
* cannotBeExecutedInTransaction:
|
||||||
* Indicates whether the statement cannot be executed in a transaction. If
|
* Indicates whether the statement cannot be executed in a transaction. If
|
||||||
* this is set to true, the statement will be executed directly on the main
|
* this is set to true, the statement will be executed directly on the main
|
||||||
* database because there are no transactional visibility issues for such
|
* database because there are no transactional visibility issues for such
|
||||||
* commands.
|
* commands.
|
||||||
*
|
*
|
||||||
* And when this is true, we don't expect getMarkDistributedParams and
|
* checkSupportedObjectType:
|
||||||
* getUnmarkDistributedParams to be implemented.
|
* Callback function that checks whether type of the object referred to by
|
||||||
|
* given statement is supported. Can be NULL if not applicable for the
|
||||||
|
* statement type.
|
||||||
*/
|
*/
|
||||||
typedef struct NonMainDbDistributeObjectOps
|
typedef struct NonMainDbDistributeObjectOps
|
||||||
{
|
{
|
||||||
MarkDistributedGloballyParams * (*getMarkDistributedParams)(Node * parsetree);
|
|
||||||
List * (*getUnmarkDistributedParams)(Node * parsetree);
|
|
||||||
bool cannotBeExecutedInTransaction;
|
bool cannotBeExecutedInTransaction;
|
||||||
|
bool (*checkSupportedObjectType)(Node *parsetree);
|
||||||
} NonMainDbDistributeObjectOps;
|
} NonMainDbDistributeObjectOps;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getMarkDistributedParams and getUnmarkDistributedParams callbacks for
|
* checkSupportedObjectType callbacks for OperationArray.
|
||||||
* NonMainDbDistributeObjectOps.
|
|
||||||
*/
|
*/
|
||||||
static MarkDistributedGloballyParams * CreateRoleStmtGetMarkDistributedParams(
|
static bool CreateDbStmtCheckSupportedObjectType(Node *node);
|
||||||
Node *parsetree);
|
static bool DropDbStmtCheckSupportedObjectType(Node *node);
|
||||||
static List * DropRoleStmtGetUnmarkDistributedParams(Node *parsetree);
|
static bool GrantStmtCheckSupportedObjectType(Node *node);
|
||||||
|
static bool SecLabelStmtCheckSupportedObjectType(Node *node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NonMainDbDistributeObjectOps for different command types.
|
* OperationArray that holds NonMainDbDistributeObjectOps for different command types.
|
||||||
*
|
|
||||||
* Naming of these structs are stolen from distribute_object_ops.c. We use
|
|
||||||
* "Any" if the command doesn't have any other variations or if the struct
|
|
||||||
* implements it for all its variations. For example, while we name the struct
|
|
||||||
* for CreateRoleStmt as Any_CreateRole, we name the struct that implements
|
|
||||||
* SecLabelStmt for role objects as Role_SecLabel.
|
|
||||||
*/
|
*/
|
||||||
static const NonMainDbDistributeObjectOps Any_CreateRole = {
|
static const NonMainDbDistributeObjectOps *const OperationArray[] = {
|
||||||
.getMarkDistributedParams = CreateRoleStmtGetMarkDistributedParams,
|
[T_CreateRoleStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
.getUnmarkDistributedParams = NULL,
|
.cannotBeExecutedInTransaction = false,
|
||||||
.cannotBeExecutedInTransaction = false
|
.checkSupportedObjectType = NULL
|
||||||
};
|
},
|
||||||
static const NonMainDbDistributeObjectOps Any_DropRole = {
|
[T_DropRoleStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
.getMarkDistributedParams = NULL,
|
.cannotBeExecutedInTransaction = false,
|
||||||
.getUnmarkDistributedParams = DropRoleStmtGetUnmarkDistributedParams,
|
.checkSupportedObjectType = NULL
|
||||||
.cannotBeExecutedInTransaction = false
|
},
|
||||||
};
|
[T_AlterRoleStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
static const NonMainDbDistributeObjectOps Any_AlterRole = {
|
.cannotBeExecutedInTransaction = false,
|
||||||
.getMarkDistributedParams = NULL,
|
.checkSupportedObjectType = NULL
|
||||||
.getUnmarkDistributedParams = NULL,
|
},
|
||||||
.cannotBeExecutedInTransaction = false
|
[T_GrantRoleStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
};
|
.cannotBeExecutedInTransaction = false,
|
||||||
static const NonMainDbDistributeObjectOps Any_GrantRole = {
|
.checkSupportedObjectType = NULL
|
||||||
.getMarkDistributedParams = NULL,
|
},
|
||||||
.getUnmarkDistributedParams = NULL,
|
[T_CreatedbStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
.cannotBeExecutedInTransaction = false
|
.cannotBeExecutedInTransaction = true,
|
||||||
};
|
.checkSupportedObjectType = CreateDbStmtCheckSupportedObjectType
|
||||||
static const NonMainDbDistributeObjectOps Any_CreateDatabase = {
|
},
|
||||||
.getMarkDistributedParams = NULL,
|
[T_DropdbStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
.getUnmarkDistributedParams = NULL,
|
.cannotBeExecutedInTransaction = true,
|
||||||
.cannotBeExecutedInTransaction = true
|
.checkSupportedObjectType = DropDbStmtCheckSupportedObjectType
|
||||||
};
|
},
|
||||||
static const NonMainDbDistributeObjectOps Any_DropDatabase = {
|
[T_GrantStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
.getMarkDistributedParams = NULL,
|
.cannotBeExecutedInTransaction = false,
|
||||||
.getUnmarkDistributedParams = NULL,
|
.checkSupportedObjectType = GrantStmtCheckSupportedObjectType
|
||||||
.cannotBeExecutedInTransaction = true
|
},
|
||||||
};
|
[T_SecLabelStmt] = &(NonMainDbDistributeObjectOps) {
|
||||||
|
.cannotBeExecutedInTransaction = false,
|
||||||
static const NonMainDbDistributeObjectOps Any_AlterDatabase = {
|
.checkSupportedObjectType = SecLabelStmtCheckSupportedObjectType
|
||||||
.getMarkDistributedParams = NULL,
|
},
|
||||||
.getUnmarkDistributedParams = NULL,
|
|
||||||
.cannotBeExecutedInTransaction = true
|
|
||||||
};
|
|
||||||
|
|
||||||
static const NonMainDbDistributeObjectOps Any_AlterDatabaseSet = {
|
|
||||||
.getMarkDistributedParams = NULL,
|
|
||||||
.getUnmarkDistributedParams = NULL,
|
|
||||||
.cannotBeExecutedInTransaction = true
|
|
||||||
};
|
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= PG_VERSION_15
|
|
||||||
static const NonMainDbDistributeObjectOps Any_AlterDatabaseRefreshColl = {
|
|
||||||
.getMarkDistributedParams = NULL,
|
|
||||||
.getUnmarkDistributedParams = NULL,
|
|
||||||
.cannotBeExecutedInTransaction = false
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const NonMainDbDistributeObjectOps Database_Grant = {
|
|
||||||
.getMarkDistributedParams = NULL,
|
|
||||||
.getUnmarkDistributedParams = NULL,
|
|
||||||
.cannotBeExecutedInTransaction = false
|
|
||||||
};
|
|
||||||
static const NonMainDbDistributeObjectOps Role_SecLabel = {
|
|
||||||
.getMarkDistributedParams = NULL,
|
|
||||||
.getUnmarkDistributedParams = NULL,
|
|
||||||
.cannotBeExecutedInTransaction = false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* other static function declarations */
|
/* other static function declarations */
|
||||||
const NonMainDbDistributeObjectOps * GetNonMainDbDistributeObjectOps(Node *parsetree);
|
const NonMainDbDistributeObjectOps * GetNonMainDbDistributeObjectOps(Node *parsetree);
|
||||||
static void MarkObjectDistributedGloballyOnMainDbs(
|
static void CreateRoleStmtMarkDistGloballyOnMainDbs(CreateRoleStmt *createRoleStmt);
|
||||||
MarkDistributedGloballyParams *markDistributedParams);
|
static void DropRoleStmtUnmarkDistOnLocalMainDb(DropRoleStmt *dropRoleStmt);
|
||||||
static void UnmarkObjectsDistributedOnLocalMainDb(List *unmarkDistributedParamsList);
|
static void MarkObjectDistributedGloballyOnMainDbs(Oid catalogRelId, Oid objectId,
|
||||||
|
char *objectName);
|
||||||
|
static void UnmarkObjectDistributedOnLocalMainDb(uint16 catalogRelId, Oid objectId);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -249,10 +172,9 @@ RunPreprocessNonMainDBCommand(Node *parsetree)
|
||||||
quote_literal_cstr(CurrentUserName()));
|
quote_literal_cstr(CurrentUserName()));
|
||||||
RunCitusMainDBQuery(mainDBQuery->data);
|
RunCitusMainDBQuery(mainDBQuery->data);
|
||||||
|
|
||||||
if (ops->getUnmarkDistributedParams)
|
if (IsA(parsetree, DropRoleStmt))
|
||||||
{
|
{
|
||||||
List *unmarkDistributedParamsList = ops->getUnmarkDistributedParams(parsetree);
|
DropRoleStmtUnmarkDistOnLocalMainDb((DropRoleStmt *) parsetree);
|
||||||
UnmarkObjectsDistributedOnLocalMainDb(unmarkDistributedParamsList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -266,22 +188,14 @@ RunPreprocessNonMainDBCommand(Node *parsetree)
|
||||||
void
|
void
|
||||||
RunPostprocessNonMainDBCommand(Node *parsetree)
|
RunPostprocessNonMainDBCommand(Node *parsetree)
|
||||||
{
|
{
|
||||||
if (IsMainDB)
|
if (IsMainDB || !GetNonMainDbDistributeObjectOps(parsetree))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonMainDbDistributeObjectOps *ops = GetNonMainDbDistributeObjectOps(parsetree);
|
if (IsA(parsetree, CreateRoleStmt))
|
||||||
if (!ops)
|
|
||||||
{
|
{
|
||||||
return;
|
CreateRoleStmtMarkDistGloballyOnMainDbs((CreateRoleStmt *) parsetree);
|
||||||
}
|
|
||||||
|
|
||||||
if (ops->getMarkDistributedParams)
|
|
||||||
{
|
|
||||||
MarkDistributedGloballyParams *markDistributedParams =
|
|
||||||
ops->getMarkDistributedParams(parsetree);
|
|
||||||
MarkObjectDistributedGloballyOnMainDbs(markDistributedParams);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,137 +208,63 @@ RunPostprocessNonMainDBCommand(Node *parsetree)
|
||||||
const NonMainDbDistributeObjectOps *
|
const NonMainDbDistributeObjectOps *
|
||||||
GetNonMainDbDistributeObjectOps(Node *parsetree)
|
GetNonMainDbDistributeObjectOps(Node *parsetree)
|
||||||
{
|
{
|
||||||
switch (nodeTag(parsetree))
|
NodeTag tag = nodeTag(parsetree);
|
||||||
|
if (tag >= lengthof(OperationArray))
|
||||||
{
|
{
|
||||||
case T_CreateRoleStmt:
|
return NULL;
|
||||||
{
|
|
||||||
return &Any_CreateRole;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case T_DropRoleStmt:
|
const NonMainDbDistributeObjectOps *ops = OperationArray[tag];
|
||||||
|
|
||||||
|
if (ops == NULL)
|
||||||
{
|
{
|
||||||
return &Any_DropRole;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
case T_AlterRoleStmt:
|
if (!ops->checkSupportedObjectType ||
|
||||||
|
ops->checkSupportedObjectType(parsetree))
|
||||||
{
|
{
|
||||||
return &Any_AlterRole;
|
return ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
case T_GrantRoleStmt:
|
return NULL;
|
||||||
{
|
}
|
||||||
return &Any_GrantRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_CreatedbStmt:
|
|
||||||
{
|
|
||||||
CreatedbStmt *stmt = castNode(CreatedbStmt, parsetree);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't try to send the query to the main database if the CREATE
|
* CreateRoleStmtMarkDistGloballyOnMainDbs marks the role as
|
||||||
* DATABASE command is for the main database itself, this is a very
|
* distributed on all main databases globally.
|
||||||
* rare case but it's exercised by our test suite.
|
|
||||||
*/
|
*/
|
||||||
if (strcmp(stmt->dbname, MainDb) != 0)
|
static void
|
||||||
{
|
CreateRoleStmtMarkDistGloballyOnMainDbs(CreateRoleStmt *createRoleStmt)
|
||||||
return &Any_CreateDatabase;
|
{
|
||||||
}
|
/* object must exist as we've just created it */
|
||||||
|
bool missingOk = false;
|
||||||
|
Oid roleId = get_role_oid(createRoleStmt->role, missingOk);
|
||||||
|
|
||||||
return NULL;
|
MarkObjectDistributedGloballyOnMainDbs(AuthIdRelationId, roleId,
|
||||||
}
|
createRoleStmt->role);
|
||||||
|
}
|
||||||
|
|
||||||
case T_DropdbStmt:
|
|
||||||
{
|
|
||||||
DropdbStmt *stmt = castNode(DropdbStmt, parsetree);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't try to send the query to the main database if the DROP
|
* DropRoleStmtUnmarkDistOnLocalMainDb unmarks the roles as
|
||||||
* DATABASE command is for the main database itself, this is a very
|
* distributed on the local main database.
|
||||||
* rare case but it's exercised by our test suite.
|
|
||||||
*/
|
*/
|
||||||
if (strcmp(stmt->dbname, MainDb) != 0)
|
static void
|
||||||
|
DropRoleStmtUnmarkDistOnLocalMainDb(DropRoleStmt *dropRoleStmt)
|
||||||
|
{
|
||||||
|
RoleSpec *roleSpec = NULL;
|
||||||
|
foreach_ptr(roleSpec, dropRoleStmt->roles)
|
||||||
{
|
{
|
||||||
return &Any_DropDatabase;
|
Oid roleOid = get_role_oid(roleSpec->rolename,
|
||||||
}
|
dropRoleStmt->missing_ok);
|
||||||
|
if (roleOid == InvalidOid)
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_AlterDatabaseStmt:
|
|
||||||
{
|
{
|
||||||
AlterDatabaseStmt *stmt = castNode(AlterDatabaseStmt, parsetree);
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't try to send the query to the main database if the ALTER
|
|
||||||
* DATABASE command is for the main database itself, this is a very
|
|
||||||
* rare case but it's exercised by our test suite.
|
|
||||||
*/
|
|
||||||
if (strcmp(stmt->dbname, MainDb) != 0)
|
|
||||||
{
|
|
||||||
return &Any_AlterDatabase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
UnmarkObjectDistributedOnLocalMainDb(AuthIdRelationId, roleOid);
|
||||||
}
|
|
||||||
|
|
||||||
case T_AlterDatabaseSetStmt:
|
|
||||||
{
|
|
||||||
AlterDatabaseSetStmt *stmt = castNode(AlterDatabaseSetStmt, parsetree);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't try to send the query to the main database if the ALTER
|
|
||||||
* DATABASE command is for the main database itself, this is a very
|
|
||||||
* rare case but it's exercised by our test suite.
|
|
||||||
*/
|
|
||||||
if (strcmp(stmt->dbname, MainDb) != 0)
|
|
||||||
{
|
|
||||||
return &Any_AlterDatabaseSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= PG_VERSION_15
|
|
||||||
case T_AlterDatabaseRefreshCollStmt:
|
|
||||||
{
|
|
||||||
return &Any_AlterDatabaseRefreshColl;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case T_GrantStmt:
|
|
||||||
{
|
|
||||||
GrantStmt *stmt = castNode(GrantStmt, parsetree);
|
|
||||||
|
|
||||||
switch (stmt->objtype)
|
|
||||||
{
|
|
||||||
case OBJECT_DATABASE:
|
|
||||||
{
|
|
||||||
return &Database_Grant;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case T_SecLabelStmt:
|
|
||||||
{
|
|
||||||
SecLabelStmt *stmt = castNode(SecLabelStmt, parsetree);
|
|
||||||
|
|
||||||
switch (stmt->objtype)
|
|
||||||
{
|
|
||||||
case OBJECT_ROLE:
|
|
||||||
{
|
|
||||||
return &Role_SecLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,90 +274,78 @@ GetNonMainDbDistributeObjectOps(Node *parsetree)
|
||||||
* distributed on all main databases globally.
|
* distributed on all main databases globally.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
MarkObjectDistributedGloballyOnMainDbs(
|
MarkObjectDistributedGloballyOnMainDbs(Oid catalogRelId, Oid objectId, char *objectName)
|
||||||
MarkDistributedGloballyParams *markDistributedParams)
|
|
||||||
{
|
{
|
||||||
StringInfo mainDBQuery = makeStringInfo();
|
StringInfo mainDBQuery = makeStringInfo();
|
||||||
appendStringInfo(mainDBQuery,
|
appendStringInfo(mainDBQuery,
|
||||||
MARK_OBJECT_DISTRIBUTED,
|
MARK_OBJECT_DISTRIBUTED,
|
||||||
markDistributedParams->catalogRelId,
|
catalogRelId,
|
||||||
quote_literal_cstr(markDistributedParams->name),
|
quote_literal_cstr(objectName),
|
||||||
markDistributedParams->id,
|
objectId,
|
||||||
quote_literal_cstr(CurrentUserName()));
|
quote_literal_cstr(CurrentUserName()));
|
||||||
RunCitusMainDBQuery(mainDBQuery->data);
|
RunCitusMainDBQuery(mainDBQuery->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UnmarkObjectsDistributedOnLocalMainDb unmarks a list of objects as
|
* UnmarkObjectDistributedOnLocalMainDb unmarks an object as
|
||||||
* distributed on the local main database.
|
* distributed on the local main database.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
UnmarkObjectsDistributedOnLocalMainDb(List *unmarkDistributedParamsList)
|
UnmarkObjectDistributedOnLocalMainDb(uint16 catalogRelId, Oid objectId)
|
||||||
{
|
{
|
||||||
int subObjectId = 0;
|
const int subObjectId = 0;
|
||||||
char *checkObjectExistence = "false";
|
const char *checkObjectExistence = "false";
|
||||||
|
|
||||||
UnmarkDistributedLocallyParams *unmarkDistributedParams = NULL;
|
|
||||||
foreach_ptr(unmarkDistributedParams, unmarkDistributedParamsList)
|
|
||||||
{
|
|
||||||
StringInfo query = makeStringInfo();
|
StringInfo query = makeStringInfo();
|
||||||
appendStringInfo(query,
|
appendStringInfo(query,
|
||||||
UNMARK_OBJECT_DISTRIBUTED,
|
UNMARK_OBJECT_DISTRIBUTED,
|
||||||
unmarkDistributedParams->catalogRelId,
|
catalogRelId, objectId,
|
||||||
unmarkDistributedParams->id,
|
|
||||||
subObjectId, checkObjectExistence);
|
subObjectId, checkObjectExistence);
|
||||||
RunCitusMainDBQuery(query->data);
|
RunCitusMainDBQuery(query->data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getMarkDistributedParams and getUnmarkDistributedParams callback implementations
|
* checkSupportedObjectTypes callbacks for OperationArray lie below.
|
||||||
* for NonMainDbDistributeObjectOps start here.
|
|
||||||
*/
|
*/
|
||||||
static MarkDistributedGloballyParams *
|
static bool
|
||||||
CreateRoleStmtGetMarkDistributedParams(Node *parsetree)
|
CreateDbStmtCheckSupportedObjectType(Node *node)
|
||||||
{
|
{
|
||||||
CreateRoleStmt *stmt = castNode(CreateRoleStmt, parsetree);
|
/*
|
||||||
MarkDistributedGloballyParams *params =
|
* We don't try to send the query to the main database if the CREATE
|
||||||
(MarkDistributedGloballyParams *) palloc(sizeof(MarkDistributedGloballyParams));
|
* DATABASE command is for the main database itself, this is a very
|
||||||
params->name = stmt->role;
|
* rare case but it's exercised by our test suite.
|
||||||
params->catalogRelId = AuthIdRelationId;
|
*/
|
||||||
|
CreatedbStmt *stmt = castNode(CreatedbStmt, node);
|
||||||
/* object must exist as we've just created it */
|
return strcmp(stmt->dbname, MainDb) != 0;
|
||||||
bool missingOk = false;
|
|
||||||
params->id = get_role_oid(stmt->role, missingOk);
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static List *
|
static bool
|
||||||
DropRoleStmtGetUnmarkDistributedParams(Node *parsetree)
|
DropDbStmtCheckSupportedObjectType(Node *node)
|
||||||
{
|
{
|
||||||
DropRoleStmt *stmt = castNode(DropRoleStmt, parsetree);
|
/*
|
||||||
|
* We don't try to send the query to the main database if the DROP
|
||||||
List *paramsList = NIL;
|
* DATABASE command is for the main database itself, this is a very
|
||||||
|
* rare case but it's exercised by our test suite.
|
||||||
RoleSpec *roleSpec = NULL;
|
*/
|
||||||
foreach_ptr(roleSpec, stmt->roles)
|
DropdbStmt *stmt = castNode(DropdbStmt, node);
|
||||||
{
|
return strcmp(stmt->dbname, MainDb) != 0;
|
||||||
UnmarkDistributedLocallyParams *params =
|
}
|
||||||
(UnmarkDistributedLocallyParams *) palloc(
|
|
||||||
sizeof(UnmarkDistributedLocallyParams));
|
|
||||||
|
static bool
|
||||||
Oid roleOid = get_role_oid(roleSpec->rolename, stmt->missing_ok);
|
GrantStmtCheckSupportedObjectType(Node *node)
|
||||||
if (roleOid == InvalidOid)
|
{
|
||||||
{
|
GrantStmt *stmt = castNode(GrantStmt, node);
|
||||||
continue;
|
return stmt->objtype == OBJECT_DATABASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
params->id = roleOid;
|
|
||||||
params->catalogRelId = AuthIdRelationId;
|
static bool
|
||||||
|
SecLabelStmtCheckSupportedObjectType(Node *node)
|
||||||
paramsList = lappend(paramsList, params);
|
{
|
||||||
}
|
SecLabelStmt *stmt = castNode(SecLabelStmt, node);
|
||||||
|
return stmt->objtype == OBJECT_ROLE;
|
||||||
return paramsList;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,18 +491,17 @@ GenerateRoleOptionsList(HeapTuple tuple)
|
||||||
options = lappend(options, makeDefElem("password", NULL, -1));
|
options = lappend(options, makeDefElem("password", NULL, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load valid unitl data from the heap tuple, use default of infinity if not set */
|
/* load valid until data from the heap tuple */
|
||||||
Datum rolValidUntilDatum = SysCacheGetAttr(AUTHNAME, tuple,
|
Datum rolValidUntilDatum = SysCacheGetAttr(AUTHNAME, tuple,
|
||||||
Anum_pg_authid_rolvaliduntil, &isNull);
|
Anum_pg_authid_rolvaliduntil, &isNull);
|
||||||
char *rolValidUntil = "infinity";
|
|
||||||
if (!isNull)
|
if (!isNull)
|
||||||
{
|
{
|
||||||
rolValidUntil = pstrdup((char *) timestamptz_to_str(rolValidUntilDatum));
|
char *rolValidUntil = pstrdup((char *) timestamptz_to_str(rolValidUntilDatum));
|
||||||
}
|
|
||||||
|
|
||||||
Node *validUntilStringNode = (Node *) makeString(rolValidUntil);
|
Node *validUntilStringNode = (Node *) makeString(rolValidUntil);
|
||||||
DefElem *validUntilOption = makeDefElem("validUntil", validUntilStringNode, -1);
|
DefElem *validUntilOption = makeDefElem("validUntil", validUntilStringNode, -1);
|
||||||
options = lappend(options, validUntilOption);
|
options = lappend(options, validUntilOption);
|
||||||
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3053,11 +3053,15 @@ ErrorUnsupportedAlterTableAddColumn(Oid relationId, AlterTableCmd *command,
|
||||||
else if (constraint->contype == CONSTR_FOREIGN)
|
else if (constraint->contype == CONSTR_FOREIGN)
|
||||||
{
|
{
|
||||||
RangeVar *referencedTable = constraint->pktable;
|
RangeVar *referencedTable = constraint->pktable;
|
||||||
char *referencedColumn = strVal(lfirst(list_head(constraint->pk_attrs)));
|
|
||||||
Oid referencedRelationId = RangeVarGetRelid(referencedTable, NoLock, false);
|
Oid referencedRelationId = RangeVarGetRelid(referencedTable, NoLock, false);
|
||||||
|
|
||||||
appendStringInfo(errHint, "FOREIGN KEY (%s) REFERENCES %s(%s)", colName,
|
appendStringInfo(errHint, "FOREIGN KEY (%s) REFERENCES %s", colName,
|
||||||
get_rel_name(referencedRelationId), referencedColumn);
|
get_rel_name(referencedRelationId));
|
||||||
|
|
||||||
|
if (list_length(constraint->pk_attrs) > 0)
|
||||||
|
{
|
||||||
|
AppendColumnNameList(errHint, constraint->pk_attrs);
|
||||||
|
}
|
||||||
|
|
||||||
if (constraint->fk_del_action == FKCONSTR_ACTION_SETNULL)
|
if (constraint->fk_del_action == FKCONSTR_ACTION_SETNULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,7 +121,7 @@ AppendAlterTableStmt(StringInfo buf, AlterTableStmt *stmt)
|
||||||
* AppendColumnNameList converts a list of columns into comma separated string format
|
* AppendColumnNameList converts a list of columns into comma separated string format
|
||||||
* (colname_1, colname_2, .., colname_n).
|
* (colname_1, colname_2, .., colname_n).
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
AppendColumnNameList(StringInfo buf, List *columns)
|
AppendColumnNameList(StringInfo buf, List *columns)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, " (");
|
appendStringInfoString(buf, " (");
|
||||||
|
|
|
@ -492,19 +492,7 @@ stop_metadata_sync_to_node(PG_FUNCTION_ARGS)
|
||||||
bool
|
bool
|
||||||
ClusterHasKnownMetadataWorkers()
|
ClusterHasKnownMetadataWorkers()
|
||||||
{
|
{
|
||||||
bool workerWithMetadata = false;
|
return !IsCoordinator() || HasMetadataWorkers();
|
||||||
|
|
||||||
if (!IsCoordinator())
|
|
||||||
{
|
|
||||||
workerWithMetadata = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workerWithMetadata || HasMetadataWorkers())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
#include "utils/xid8.h"
|
#include "utils/xid8.h"
|
||||||
|
|
||||||
#include "pg_version_constants.h"
|
#include "pg_version_constants.h"
|
||||||
|
@ -261,11 +262,28 @@ RecoverWorkerTransactions(WorkerNode *workerNode)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the transaction is created by an outer transaction from a non-main database */
|
|
||||||
bool outerXidIsNull = false;
|
bool outerXidIsNull = false;
|
||||||
Datum outerXidDatum = heap_getattr(heapTuple,
|
Datum outerXidDatum = 0;
|
||||||
|
if (EnableVersionChecks ||
|
||||||
|
SearchSysCacheExistsAttName(DistTransactionRelationId(), "outer_xid"))
|
||||||
|
{
|
||||||
|
/* Check if the transaction is created by an outer transaction from a non-main database */
|
||||||
|
outerXidDatum = heap_getattr(heapTuple,
|
||||||
Anum_pg_dist_transaction_outerxid,
|
Anum_pg_dist_transaction_outerxid,
|
||||||
tupleDescriptor, &outerXidIsNull);
|
tupleDescriptor, &outerXidIsNull);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Normally we don't try to recover prepared transactions when the
|
||||||
|
* binary version doesn't match the sql version. However, we skip
|
||||||
|
* those checks in regression tests by disabling
|
||||||
|
* citus.enable_version_checks. And when this is the case, while
|
||||||
|
* the C code looks for "outer_xid" attribute, pg_dist_transaction
|
||||||
|
* doesn't yet have it.
|
||||||
|
*/
|
||||||
|
Assert(!EnableVersionChecks);
|
||||||
|
}
|
||||||
|
|
||||||
TransactionId outerXid = 0;
|
TransactionId outerXid = 0;
|
||||||
if (!outerXidIsNull)
|
if (!outerXidIsNull)
|
||||||
|
|
|
@ -121,6 +121,8 @@ extern void AppendGrantedByInGrant(StringInfo buf, GrantStmt *stmt);
|
||||||
extern void AppendGrantSharedPrefix(StringInfo buf, GrantStmt *stmt);
|
extern void AppendGrantSharedPrefix(StringInfo buf, GrantStmt *stmt);
|
||||||
extern void AppendGrantSharedSuffix(StringInfo buf, GrantStmt *stmt);
|
extern void AppendGrantSharedSuffix(StringInfo buf, GrantStmt *stmt);
|
||||||
|
|
||||||
|
extern void AppendColumnNameList(StringInfo buf, List *columns);
|
||||||
|
|
||||||
/* Common deparser utils */
|
/* Common deparser utils */
|
||||||
|
|
||||||
typedef struct DefElemOptionFormat
|
typedef struct DefElemOptionFormat
|
||||||
|
|
|
@ -44,6 +44,15 @@ ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and
|
||||||
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
||||||
HINT: You can issue each command separately such as ALTER TABLE referencing ADD COLUMN test_8 data_type; ALTER TABLE referencing ADD CONSTRAINT constraint_name CHECK (check_expression);
|
HINT: You can issue each command separately such as ALTER TABLE referencing ADD COLUMN test_8 data_type; ALTER TABLE referencing ADD CONSTRAINT constraint_name CHECK (check_expression);
|
||||||
ALTER TABLE referencing ADD COLUMN test_8 integer CONSTRAINT check_test_8 CHECK (test_8 > 0);
|
ALTER TABLE referencing ADD COLUMN test_8 integer CONSTRAINT check_test_8 CHECK (test_8 > 0);
|
||||||
|
-- error out properly even if the REFERENCES does not include the column list of the referenced table
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_9 bool, ADD COLUMN test_10 int REFERENCES referenced;
|
||||||
|
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
||||||
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
||||||
|
HINT: You can issue each command separately such as ALTER TABLE referencing ADD COLUMN test_10 data_type; ALTER TABLE referencing ADD CONSTRAINT constraint_name FOREIGN KEY (test_10) REFERENCES referenced;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_9 bool, ADD COLUMN test_10 int REFERENCES referenced(int_col);
|
||||||
|
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
||||||
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
||||||
|
HINT: You can issue each command separately such as ALTER TABLE referencing ADD COLUMN test_10 data_type; ALTER TABLE referencing ADD CONSTRAINT constraint_name FOREIGN KEY (test_10) REFERENCES referenced (int_col );
|
||||||
-- try to add test_6 again, but with IF NOT EXISTS
|
-- try to add test_6 again, but with IF NOT EXISTS
|
||||||
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 text;
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 text;
|
||||||
NOTICE: column "test_6" of relation "referencing" already exists, skipping
|
NOTICE: column "test_6" of relation "referencing" already exists, skipping
|
||||||
|
|
|
@ -121,17 +121,17 @@ SELECT 1 FROM master_add_node('localhost', :worker_2_port);
|
||||||
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname;
|
SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname;
|
||||||
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil
|
rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
create_group | f | t | f | f | f | f | f | -1 | | infinity
|
create_group | f | t | f | f | f | f | f | -1 | |
|
||||||
create_group_2 | f | t | f | f | f | f | f | -1 | | infinity
|
create_group_2 | f | t | f | f | f | f | f | -1 | |
|
||||||
create_role | f | t | f | f | f | f | f | -1 | | infinity
|
create_role | f | t | f | f | f | f | f | -1 | |
|
||||||
create_role"edge | f | t | f | f | f | f | f | -1 | | infinity
|
create_role"edge | f | t | f | f | f | f | f | -1 | |
|
||||||
create_role'edge | f | t | f | f | f | f | f | -1 | | infinity
|
create_role'edge | f | t | f | f | f | f | f | -1 | |
|
||||||
create_role_2 | f | t | f | f | f | f | f | -1 | | infinity
|
create_role_2 | f | t | f | f | f | f | f | -1 | |
|
||||||
create_role_sysid | f | t | f | f | f | f | f | -1 | | infinity
|
create_role_sysid | f | t | f | f | f | f | f | -1 | |
|
||||||
create_role_with_everything | t | t | t | t | t | t | t | 105 | t | Thu May 04 17:00:00 2045 PDT
|
create_role_with_everything | t | t | t | t | t | t | t | 105 | t | Thu May 04 17:00:00 2045 PDT
|
||||||
create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT
|
create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT
|
||||||
create_user | f | t | f | f | t | f | f | -1 | | infinity
|
create_user | f | t | f | f | t | f | f | -1 | |
|
||||||
create_user_2 | f | t | f | f | t | f | f | -1 | | infinity
|
create_user_2 | f | t | f | f | t | f | f | -1 | |
|
||||||
(11 rows)
|
(11 rows)
|
||||||
|
|
||||||
SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2;
|
SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2;
|
||||||
|
|
|
@ -188,7 +188,6 @@ select 1 from citus_add_node('localhost', :worker_2_port);
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- XXX: date is not correct on one of the workers due to https://github.com/citusdata/citus/issues/7533
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
select result FROM run_command_on_all_nodes($$
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
SELECT array_to_json(array_agg(row_to_json(t)))
|
||||||
FROM (
|
FROM (
|
||||||
|
@ -204,7 +203,7 @@ $$);
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":true,"rolinherit":true,"rolcreaterole":true,"rolcreatedb":true,"rolcanlogin":true,"rolreplication":true,"rolbypassrls":true,"rolconnlimit":10,"pass_not_empty":null,"date":"2023-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":true,"rolinherit":true,"rolcreaterole":true,"rolcreatedb":true,"rolcanlogin":true,"rolreplication":true,"rolbypassrls":true,"rolconnlimit":10,"pass_not_empty":null,"date":"2023-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":true,"rolinherit":true,"rolcreaterole":true,"rolcreatedb":true,"rolcanlogin":true,"rolreplication":true,"rolbypassrls":true,"rolconnlimit":10,"pass_not_empty":null,"date":"2023-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":true,"rolinherit":true,"rolcreaterole":true,"rolcreatedb":true,"rolcanlogin":true,"rolreplication":true,"rolbypassrls":true,"rolconnlimit":10,"pass_not_empty":null,"date":"2023-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":"infinity"},{"rolname":"test_role2-needs\\!escape","rolsuper":true,"rolinherit":true,"rolcreaterole":true,"rolcreatedb":true,"rolcanlogin":true,"rolreplication":true,"rolbypassrls":true,"rolconnlimit":10,"pass_not_empty":null,"date":"2023-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":"infinity"}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":true,"rolinherit":true,"rolcreaterole":true,"rolcreatedb":true,"rolcanlogin":true,"rolreplication":true,"rolbypassrls":true,"rolconnlimit":10,"pass_not_empty":null,"date":"2023-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
--test for alter user
|
--test for alter user
|
||||||
|
@ -229,7 +228,6 @@ select 1 from citus_add_node('localhost', :worker_2_port);
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- XXX: date is not correct on one of the workers due to https://github.com/citusdata/citus/issues/7533
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
select result FROM run_command_on_all_nodes($$
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
SELECT array_to_json(array_agg(row_to_json(t)))
|
||||||
FROM (
|
FROM (
|
||||||
|
@ -245,7 +243,7 @@ $$);
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":"infinity"},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":"infinity"}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
--test for drop user
|
--test for drop user
|
||||||
|
@ -266,7 +264,6 @@ select 1 from citus_add_node('localhost', :worker_2_port);
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- XXX: date is not correct on one of the workers due to https://github.com/citusdata/citus/issues/7533
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
select result FROM run_command_on_all_nodes($$
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
SELECT array_to_json(array_agg(row_to_json(t)))
|
||||||
FROM (
|
FROM (
|
||||||
|
@ -282,7 +279,7 @@ $$);
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":"infinity"},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":"infinity"}]
|
[{"rolname":"test_role1","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":true,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":true,"date":null},{"rolname":"test_role2-needs\\!escape","rolsuper":false,"rolinherit":false,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":5,"pass_not_empty":null,"date":"2024-01-01"},{"rolname":"test_role3","rolsuper":false,"rolinherit":true,"rolcreaterole":false,"rolcreatedb":false,"rolcanlogin":false,"rolreplication":false,"rolbypassrls":false,"rolconnlimit":-1,"pass_not_empty":null,"date":null}]
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
-- Clean up: drop the database on worker node 2
|
-- Clean up: drop the database on worker node 2
|
||||||
|
|
|
@ -167,9 +167,9 @@ SELECT node_type, result FROM get_citus_tests_label_provider_labels('"user 2"')
|
||||||
SET citus.log_remote_commands TO on;
|
SET citus.log_remote_commands TO on;
|
||||||
SET citus.grep_remote_commands = '%SECURITY LABEL%';
|
SET citus.grep_remote_commands = '%SECURITY LABEL%';
|
||||||
SELECT 1 FROM citus_add_node('localhost', :worker_2_port);
|
SELECT 1 FROM citus_add_node('localhost', :worker_2_port);
|
||||||
NOTICE: issuing SELECT worker_create_or_alter_role('user1', 'CREATE ROLE user1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE user1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE user1 IS 'citus_classified'
|
NOTICE: issuing SELECT worker_create_or_alter_role('user1', 'CREATE ROLE user1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL', 'ALTER ROLE user1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL');SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE user1 IS 'citus_classified'
|
||||||
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
|
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
|
||||||
NOTICE: issuing SELECT worker_create_or_alter_role('user 2', 'CREATE ROLE "user 2" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE "user 2" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE "user 2" IS 'citus ''!unclassified'
|
NOTICE: issuing SELECT worker_create_or_alter_role('user 2', 'CREATE ROLE "user 2" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL', 'ALTER ROLE "user 2" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL');SECURITY LABEL FOR "citus '!tests_label_provider" ON ROLE "user 2" IS 'citus ''!unclassified'
|
||||||
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
|
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
|
||||||
?column?
|
?column?
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
|
|
|
@ -67,6 +67,20 @@ SELECT 1 FROM run_command_on_workers($$SELECT pg_reload_conf()$$);
|
||||||
1
|
1
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- In the version that we use for upgrade tests (v10.2.0), we propagate
|
||||||
|
-- "valid until" to the workers as "infinity" even if it's not set. And
|
||||||
|
-- given that "postgres" role is created in the older version, "valid until"
|
||||||
|
-- is set to "infinity" on the workers while this is not the case for
|
||||||
|
-- coordinator. See https://github.com/citusdata/citus/issues/7533.
|
||||||
|
--
|
||||||
|
-- We're fixing this for new versions of Citus and we'll probably backport
|
||||||
|
-- this to some older versions too. However, v10.2.0 won't ever have this
|
||||||
|
-- fix.
|
||||||
|
--
|
||||||
|
-- For this reason, here we set "valid until" to "infinity" for all the
|
||||||
|
-- nodes so that below query doesn't report any difference between the
|
||||||
|
-- metadata on coordinator and workers.
|
||||||
|
ALTER ROLE postgres WITH VALID UNTIL 'infinity';
|
||||||
-- make sure that the metadata is consistent across all nodes
|
-- make sure that the metadata is consistent across all nodes
|
||||||
-- we exclude the distributed_object_data as they are
|
-- we exclude the distributed_object_data as they are
|
||||||
-- not sorted in the same order (as OIDs differ on the nodes)
|
-- not sorted in the same order (as OIDs differ on the nodes)
|
||||||
|
|
|
@ -41,6 +41,10 @@ ALTER TABLE referencing ADD COLUMN "test_\'!7" "simple_!\'custom_type";
|
||||||
ALTER TABLE referencing ADD COLUMN test_8 integer CHECK (test_8 > 0);
|
ALTER TABLE referencing ADD COLUMN test_8 integer CHECK (test_8 > 0);
|
||||||
ALTER TABLE referencing ADD COLUMN test_8 integer CONSTRAINT check_test_8 CHECK (test_8 > 0);
|
ALTER TABLE referencing ADD COLUMN test_8 integer CONSTRAINT check_test_8 CHECK (test_8 > 0);
|
||||||
|
|
||||||
|
-- error out properly even if the REFERENCES does not include the column list of the referenced table
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_9 bool, ADD COLUMN test_10 int REFERENCES referenced;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_9 bool, ADD COLUMN test_10 int REFERENCES referenced(int_col);
|
||||||
|
|
||||||
-- try to add test_6 again, but with IF NOT EXISTS
|
-- try to add test_6 again, but with IF NOT EXISTS
|
||||||
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 text;
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 text;
|
||||||
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 integer;
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 integer;
|
||||||
|
|
|
@ -100,7 +100,6 @@ create role test_role3;
|
||||||
\c regression - - :master_port
|
\c regression - - :master_port
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
select 1 from citus_add_node('localhost', :worker_2_port);
|
||||||
|
|
||||||
-- XXX: date is not correct on one of the workers due to https://github.com/citusdata/citus/issues/7533
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
select result FROM run_command_on_all_nodes($$
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
SELECT array_to_json(array_agg(row_to_json(t)))
|
||||||
FROM (
|
FROM (
|
||||||
|
@ -128,7 +127,6 @@ LIMIT 5 VALID UNTIL '2024-01-01';
|
||||||
\c regression - - :master_port
|
\c regression - - :master_port
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
select 1 from citus_add_node('localhost', :worker_2_port);
|
||||||
|
|
||||||
-- XXX: date is not correct on one of the workers due to https://github.com/citusdata/citus/issues/7533
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
select result FROM run_command_on_all_nodes($$
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
SELECT array_to_json(array_agg(row_to_json(t)))
|
||||||
FROM (
|
FROM (
|
||||||
|
@ -153,7 +151,6 @@ DROP ROLE test_role3;
|
||||||
\c regression - - :master_port
|
\c regression - - :master_port
|
||||||
select 1 from citus_add_node('localhost', :worker_2_port);
|
select 1 from citus_add_node('localhost', :worker_2_port);
|
||||||
|
|
||||||
-- XXX: date is not correct on one of the workers due to https://github.com/citusdata/citus/issues/7533
|
|
||||||
select result FROM run_command_on_all_nodes($$
|
select result FROM run_command_on_all_nodes($$
|
||||||
SELECT array_to_json(array_agg(row_to_json(t)))
|
SELECT array_to_json(array_agg(row_to_json(t)))
|
||||||
FROM (
|
FROM (
|
||||||
|
|
|
@ -27,6 +27,21 @@ SET datestyle = "ISO, YMD";
|
||||||
SELECT 1 FROM run_command_on_workers($$ALTER SYSTEM SET datestyle = "ISO, YMD";$$);
|
SELECT 1 FROM run_command_on_workers($$ALTER SYSTEM SET datestyle = "ISO, YMD";$$);
|
||||||
SELECT 1 FROM run_command_on_workers($$SELECT pg_reload_conf()$$);
|
SELECT 1 FROM run_command_on_workers($$SELECT pg_reload_conf()$$);
|
||||||
|
|
||||||
|
-- In the version that we use for upgrade tests (v10.2.0), we propagate
|
||||||
|
-- "valid until" to the workers as "infinity" even if it's not set. And
|
||||||
|
-- given that "postgres" role is created in the older version, "valid until"
|
||||||
|
-- is set to "infinity" on the workers while this is not the case for
|
||||||
|
-- coordinator. See https://github.com/citusdata/citus/issues/7533.
|
||||||
|
--
|
||||||
|
-- We're fixing this for new versions of Citus and we'll probably backport
|
||||||
|
-- this to some older versions too. However, v10.2.0 won't ever have this
|
||||||
|
-- fix.
|
||||||
|
--
|
||||||
|
-- For this reason, here we set "valid until" to "infinity" for all the
|
||||||
|
-- nodes so that below query doesn't report any difference between the
|
||||||
|
-- metadata on coordinator and workers.
|
||||||
|
ALTER ROLE postgres WITH VALID UNTIL 'infinity';
|
||||||
|
|
||||||
-- make sure that the metadata is consistent across all nodes
|
-- make sure that the metadata is consistent across all nodes
|
||||||
-- we exclude the distributed_object_data as they are
|
-- we exclude the distributed_object_data as they are
|
||||||
-- not sorted in the same order (as OIDs differ on the nodes)
|
-- not sorted in the same order (as OIDs differ on the nodes)
|
||||||
|
|
Loading…
Reference in New Issue