Refactor alter role to work on distributed roles (#3739)

DESCRIPTION: Alter role only works for citus managed roles

Alter role was implemented before we implemented good role management that hooks into the object propagation framework. This is a refactor of all alter role commands that have been implemented to
 - be on by default
 - only work for supported roles
 - make the citus extension owner a supported role

Instead of distributing the alter role commands for roles at the beginning of the node activation role it now _only_ executes the alter role commands for all users in all databases and in the current database.

In preparation of full role support small refactors have been done in the deparser.

Earlier tests targeting other roles than the citus extension owner have been either slightly changed or removed to be put back where we have full role support.

Fixes #2549
pull/3772/head
Nils Dijk 2020-04-16 12:23:27 +02:00 committed by GitHub
parent e0eba87b6c
commit 1d6ba1d09e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 929 additions and 1031 deletions

View File

@ -196,6 +196,11 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency)
return CreateFunctionDDLCommandsIdempotent(dependency);
}
case OCLASS_ROLE:
{
return GenerateCreateOrAlterRoleCommand(dependency->objectId);
}
case OCLASS_SCHEMA:
{
char *schemaDDLCommand = CreateSchemaDDLCommand(dependency->objectId);

View File

@ -97,14 +97,14 @@ static DistributeObjectOps Any_AlterRole = {
.qualify = NULL,
.preprocess = NULL,
.postprocess = PostprocessAlterRoleStmt,
.address = NULL,
.address = AlterRoleStmtObjectAddress,
};
static DistributeObjectOps Any_AlterRoleSet = {
.deparse = DeparseAlterRoleSetStmt,
.qualify = QualifyAlterRoleSetStmt,
.preprocess = PreprocessAlterRoleSetStmt,
.postprocess = NULL,
.address = NULL,
.address = AlterRoleSetStmtObjectAddress,
};
static DistributeObjectOps Any_AlterTableMoveAll = {
.deparse = NULL,

View File

@ -18,9 +18,11 @@
#include "access/table.h"
#endif
#include "catalog/catalog.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_db_role_setting.h"
#include "catalog/pg_type.h"
#include "catalog/objectaddress.h"
#include "commands/dbcommands.h"
#include "distributed/citus_ruleutils.h"
#include "distributed/citus_safe_lib.h"
@ -29,6 +31,7 @@
#include "distributed/deparser.h"
#include "distributed/listutils.h"
#include "distributed/master_protocol.h"
#include "distributed/metadata/distobject.h"
#include "distributed/metadata_sync.h"
#include "distributed/worker_transaction.h"
#include "miscadmin.h"
@ -45,9 +48,11 @@
static const char * ExtractEncryptedPassword(Oid roleOid);
static const char * CreateAlterRoleIfExistsCommand(AlterRoleStmt *stmt);
static const char * CreateAlterRoleSetIfExistsCommand(AlterRoleSetStmt *stmt);
static bool ShouldPropagateAlterRoleSetQueries(HeapTuple tuple,
TupleDesc DbRoleSettingDescription);
static char * CreateCreateOrAlterRoleCommand(const char *roleName,
CreateRoleStmt *createRoleStmt,
AlterRoleStmt *alterRoleStmt);
static DefElem * makeDefElemInt(char *name, int value);
static List * GenerateRoleOptionsList(HeapTuple tuple);
static char * GetRoleNameFromDbRoleSetting(HeapTuple tuple,
TupleDesc DbRoleSettingDescription);
@ -59,9 +64,58 @@ static Node * makeFloatConst(char *str, int location);
static const char * WrapQueryInAlterRoleIfExistsCall(const char *query, RoleSpec *role);
static VariableSetStmt * MakeVariableSetStmt(const char *config);
static int ConfigGenericNameCompare(const void *lhs, const void *rhs);
static ObjectAddress RoleSpecToObjectAddress(RoleSpec *role, bool missing_ok);
/* controlled via GUC */
bool EnableAlterRolePropagation = false;
bool EnableAlterRolePropagation = true;
bool EnableAlterRoleSetPropagation = true;
/*
* AlterRoleStmtObjectAddress returns the ObjectAddress of the role in the
* AlterRoleStmt. If missing_ok is set to false an error will be raised if postgres
* was unable to find the role that was the target of the statement.
*/
ObjectAddress
AlterRoleStmtObjectAddress(Node *node, bool missing_ok)
{
AlterRoleStmt *stmt = castNode(AlterRoleStmt, node);
return RoleSpecToObjectAddress(stmt->role, missing_ok);
}
/*
* AlterRoleSetStmtObjectAddress returns the ObjectAddress of the role in the
* AlterRoleSetStmt. If missing_ok is set to false an error will be raised if postgres
* was unable to find the role that was the target of the statement.
*/
ObjectAddress
AlterRoleSetStmtObjectAddress(Node *node, bool missing_ok)
{
AlterRoleSetStmt *stmt = castNode(AlterRoleSetStmt, node);
return RoleSpecToObjectAddress(stmt->role, missing_ok);
}
/*
* RoleSpecToObjectAddress returns the ObjectAddress of a Role associated with a
* RoleSpec. If missing_ok is set to false an error will be raised by postgres
* explaining the Role could not be found.
*/
static ObjectAddress
RoleSpecToObjectAddress(RoleSpec *role, bool missing_ok)
{
ObjectAddress address = { 0 };
if (role != NULL)
{
/* roles can be NULL for statements on ALL roles eg. ALTER ROLE ALL SET ... */
Oid roleOid = get_rolespec_oid(role, missing_ok);
ObjectAddressSet(address, AuthIdRelationId, roleOid);
}
return address;
}
/*
@ -72,13 +126,19 @@ bool EnableAlterRolePropagation = false;
List *
PostprocessAlterRoleStmt(Node *node, const char *queryString)
{
AlterRoleStmt *stmt = castNode(AlterRoleStmt, node);
ObjectAddress address = GetObjectAddressFromParseTree(node, false);
if (!ShouldPropagateObject(&address))
{
return NIL;
}
if (!EnableAlterRolePropagation || !IsCoordinator())
{
return NIL;
}
AlterRoleStmt *stmt = castNode(AlterRoleStmt, node);
/*
* Make sure that no new nodes are added after this point until the end of the
* transaction by taking a RowShareLock on pg_dist_node, which conflicts with the
@ -120,14 +180,28 @@ PostprocessAlterRoleStmt(Node *node, const char *queryString)
List *
PreprocessAlterRoleSetStmt(Node *node, const char *queryString)
{
if (!EnableAlterRolePropagation)
if (!ShouldPropagate())
{
return NIL;
}
EnsureCoordinator();
if (!EnableAlterRoleSetPropagation)
{
return NIL;
}
AlterRoleSetStmt *stmt = castNode(AlterRoleSetStmt, node);
ObjectAddress address = GetObjectAddressFromParseTree(node, false);
/*
* stmt->role could be NULL when the statement is on 'ALL' roles, we do propagate for
* ALL roles. If it is not NULL the role is for a specific role. If that role is not
* distributed we will not propagate the statement
*/
if (stmt->role != NULL && !IsObjectDistributed(&address))
{
return NIL;
}
QualifyTreeNode((Node *) stmt);
const char *sql = DeparseTreeNode((Node *) stmt);
@ -198,6 +272,40 @@ WrapQueryInAlterRoleIfExistsCall(const char *query, RoleSpec *role)
}
/*
* CreateCreateOrAlterRoleCommand creates ALTER ROLE command, from the alter role node
* using the alter_role_if_exists() UDF.
*/
static char *
CreateCreateOrAlterRoleCommand(const char *roleName,
CreateRoleStmt *createRoleStmt,
AlterRoleStmt *alterRoleStmt)
{
StringInfoData createOrAlterRoleQueryBuffer = { 0 };
const char *createRoleQuery = "null";
const char *alterRoleQuery = "null";
if (createRoleStmt != NULL)
{
createRoleQuery = quote_literal_cstr(DeparseTreeNode((Node *) createRoleStmt));
}
if (alterRoleStmt != NULL)
{
alterRoleQuery = quote_literal_cstr(DeparseTreeNode((Node *) alterRoleStmt));
}
initStringInfo(&createOrAlterRoleQueryBuffer);
appendStringInfo(&createOrAlterRoleQueryBuffer,
"SELECT worker_create_or_alter_role(%s, %s, %s)",
quote_literal_cstr(roleName),
createRoleQuery,
alterRoleQuery);
return createOrAlterRoleQueryBuffer.data;
}
/*
* ExtractEncryptedPassword extracts the encrypted password of a role. The function
* gets the password from the pg_authid table.
@ -309,144 +417,118 @@ MakeVariableSetStmt(const char *config)
/*
* GenerateAlterRoleIfExistsCommand generate ALTER ROLE command that copies a role from
* the pg_authid table.
* GenerateRoleOptionsList returns the list of options set on a user based on the record
* in pg_authid. It requires the HeapTuple for a user entry to access both its fixed
* length and variable length fields.
*/
static const char *
GenerateAlterRoleIfExistsCommand(HeapTuple tuple, TupleDesc pgAuthIdDescription)
static List *
GenerateRoleOptionsList(HeapTuple tuple)
{
char *rolPassword = "";
char *rolValidUntil = "infinity";
bool isNull = true;
Form_pg_authid role = ((Form_pg_authid) GETSTRUCT(tuple));
AlterRoleStmt *stmt = makeNode(AlterRoleStmt);
const char *rolename = NameStr(role->rolname);
stmt->role = makeNode(RoleSpec);
stmt->role->roletype = ROLESPEC_CSTRING;
stmt->role->location = -1;
stmt->role->rolename = pstrdup(rolename);
stmt->action = 1;
stmt->options = NIL;
List *options = NIL;
options = lappend(options, makeDefElemInt("superuser", role->rolsuper));
options = lappend(options, makeDefElemInt("createdb", role->rolcreatedb));
options = lappend(options, makeDefElemInt("createrole", role->rolcreaterole));
options = lappend(options, makeDefElemInt("inherit", role->rolinherit));
options = lappend(options, makeDefElemInt("canlogin", role->rolcanlogin));
options = lappend(options, makeDefElemInt("isreplication", role->rolreplication));
options = lappend(options, makeDefElemInt("bypassrls", role->rolbypassrls));
options = lappend(options, makeDefElemInt("connectionlimit", role->rolconnlimit));
stmt->options =
lappend(stmt->options,
makeDefElemInt("superuser", role->rolsuper));
stmt->options =
lappend(stmt->options,
makeDefElemInt("createdb", role->rolcreatedb));
stmt->options =
lappend(stmt->options,
makeDefElemInt("createrole", role->rolcreaterole));
stmt->options =
lappend(stmt->options,
makeDefElemInt("inherit", role->rolinherit));
stmt->options =
lappend(stmt->options,
makeDefElemInt("canlogin", role->rolcanlogin));
stmt->options =
lappend(stmt->options,
makeDefElemInt("isreplication", role->rolreplication));
stmt->options =
lappend(stmt->options,
makeDefElemInt("bypassrls", role->rolbypassrls));
stmt->options =
lappend(stmt->options,
makeDefElemInt("connectionlimit", role->rolconnlimit));
Datum rolPasswordDatum = heap_getattr(tuple, Anum_pg_authid_rolpassword,
pgAuthIdDescription, &isNull);
/* load password from heap tuple, use NULL if not set */
bool isNull = true;
Datum rolPasswordDatum = SysCacheGetAttr(AUTHNAME, tuple, Anum_pg_authid_rolpassword,
&isNull);
if (!isNull)
{
rolPassword = pstrdup(TextDatumGetCString(rolPasswordDatum));
stmt->options = lappend(stmt->options, makeDefElem("password",
(Node *) makeString(
rolPassword),
-1));
char *rolPassword = pstrdup(TextDatumGetCString(rolPasswordDatum));
Node *passwordStringNode = (Node *) makeString(rolPassword);
DefElem *passwordOption = makeDefElem("password", passwordStringNode, -1);
options = lappend(options, passwordOption);
}
else
{
stmt->options = lappend(stmt->options, makeDefElem("password", NULL, -1));
options = lappend(options, makeDefElem("password", NULL, -1));
}
Datum rolValidUntilDatum = heap_getattr(tuple, Anum_pg_authid_rolvaliduntil,
pgAuthIdDescription, &isNull);
/* load valid unitl data from the heap tuple, use default of infinity if not set */
Datum rolValidUntilDatum = SysCacheGetAttr(AUTHNAME, tuple,
Anum_pg_authid_rolvaliduntil, &isNull);
char *rolValidUntil = "infinity";
if (!isNull)
{
rolValidUntil = pstrdup((char *) timestamptz_to_str(rolValidUntilDatum));
}
stmt->options = lappend(stmt->options, makeDefElem("validUntil",
(Node *) makeString(rolValidUntil),
-1));
Node *validUntilStringNode = (Node *) makeString(rolValidUntil);
DefElem *validUntilOption = makeDefElem("validUntil", validUntilStringNode, -1);
options = lappend(options, validUntilOption);
return CreateAlterRoleIfExistsCommand(stmt);
return options;
}
/*
* GenerateAlterRoleIfExistsCommandAllRoles creates ALTER ROLE commands
* that copies all roles from the pg_authid table.
* GenerateCreateOrAlterRoleCommand generates ALTER ROLE command that copies a role from
* the pg_authid table.
*/
List *
GenerateAlterRoleIfExistsCommandAllRoles()
GenerateCreateOrAlterRoleCommand(Oid roleOid)
{
Relation pgAuthId = heap_open(AuthIdRelationId, AccessShareLock);
TupleDesc pgAuthIdDescription = RelationGetDescr(pgAuthId);
HeapTuple tuple = NULL;
List *commands = NIL;
const char *alterRoleQuery = NULL;
HeapTuple roleTuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleOid));
Form_pg_authid role = ((Form_pg_authid) GETSTRUCT(roleTuple));
#if PG_VERSION_NUM >= PG_VERSION_12
TableScanDesc scan = table_beginscan_catalog(pgAuthId, 0, NULL);
#else
HeapScanDesc scan = heap_beginscan_catalog(pgAuthId, 0, NULL);
#endif
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
CreateRoleStmt *createRoleStmt = NULL;
AlterRoleStmt *alterRoleStmt = NULL;
if (EnableAlterRolePropagation)
{
const char *rolename = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
/*
* The default roles are skipped, because reserved roles
* cannot be altered.
*/
if (IsReservedName(rolename))
{
continue;
}
alterRoleQuery = GenerateAlterRoleIfExistsCommand(tuple, pgAuthIdDescription);
commands = lappend(commands, (void *) alterRoleQuery);
alterRoleStmt = makeNode(AlterRoleStmt);
alterRoleStmt->role = makeNode(RoleSpec);
alterRoleStmt->role->roletype = ROLESPEC_CSTRING;
alterRoleStmt->role->location = -1;
alterRoleStmt->role->rolename = pstrdup(NameStr(role->rolname));
alterRoleStmt->action = 1;
alterRoleStmt->options = GenerateRoleOptionsList(roleTuple);
}
heap_endscan(scan);
heap_close(pgAuthId, AccessShareLock);
ReleaseSysCache(roleTuple);
return commands;
List *completeRoleList = NIL;
if (createRoleStmt != NULL || alterRoleStmt != NULL)
{
/* add a worker_create_or_alter_role command if any of them are set */
char *createOrAlterRoleQuery = CreateCreateOrAlterRoleCommand(
pstrdup(NameStr(role->rolname)),
createRoleStmt,
alterRoleStmt);
completeRoleList = lappend(completeRoleList, createOrAlterRoleQuery);
}
if (EnableAlterRoleSetPropagation)
{
/* append ALTER ROLE ... SET commands fot this specific user */
List *alterRoleSetCommands = GenerateAlterRoleSetCommandForRole(roleOid);
completeRoleList = list_concat(completeRoleList, alterRoleSetCommands);
}
return completeRoleList;
}
/*
* GenerateAlterRoleSetIfExistsCommands creates ALTER ROLE .. SET commands
* that copies all session defaults for roles from the pg_db_role_setting table.
* GenerateAlterRoleSetCommandForRole returns the list of database wide settings for a
* specifc role. If the roleid is InvalidOid it returns the commands that apply to all
* users for the database or postgres wide.
*/
List *
GenerateAlterRoleSetIfExistsCommands()
GenerateAlterRoleSetCommandForRole(Oid roleid)
{
Relation DbRoleSetting = heap_open(DbRoleSettingRelationId, AccessShareLock);
TupleDesc DbRoleSettingDescription = RelationGetDescr(DbRoleSetting);
HeapTuple tuple = NULL;
List *commands = NIL;
List *alterRoleSetQueries = NIL;
#if PG_VERSION_NUM >= PG_VERSION_12
@ -457,12 +539,23 @@ GenerateAlterRoleSetIfExistsCommands()
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
if (ShouldPropagateAlterRoleSetQueries(tuple, DbRoleSettingDescription))
Form_pg_db_role_setting roleSetting = (Form_pg_db_role_setting) GETSTRUCT(tuple);
if (roleSetting->setrole != roleid)
{
alterRoleSetQueries =
GenerateAlterRoleSetIfExistsCommandList(tuple, DbRoleSettingDescription);
commands = list_concat(commands, alterRoleSetQueries);
/* not the user we are looking for */
continue;
}
if (OidIsValid(roleSetting->setdatabase) &&
roleSetting->setdatabase != MyDatabaseId)
{
/* setting is database specific for a different database */
continue;
}
List *alterRoleSetQueries = GenerateAlterRoleSetIfExistsCommandList(tuple,
DbRoleSettingDescription);
commands = list_concat(commands, alterRoleSetQueries);
}
heap_endscan(scan);
@ -683,47 +776,3 @@ ConfigGenericNameCompare(const void *a, const void *b)
*/
return pg_strcasecmp(confa->name, confb->name);
}
/*
* ShouldPropagateAlterRoleSetQueries decides if the set of AlterRoleSetStmt
* queries should be propagated to worker nodes
*
* A single DbRoleSetting tuple can be used to create multiple AlterRoleSetStmt
* queries as all of the configs are stored in a text[] column and each entry
* creates a seperate statement
*/
static bool
ShouldPropagateAlterRoleSetQueries(HeapTuple tuple,
TupleDesc DbRoleSettingDescription)
{
if (!ShouldPropagate())
{
return false;
}
const char *currentDatabaseName = CurrentDatabaseName();
const char *databaseName =
GetDatabaseNameFromDbRoleSetting(tuple, DbRoleSettingDescription);
const char *roleName = GetRoleNameFromDbRoleSetting(tuple, DbRoleSettingDescription);
/*
* session defaults for databases other than the current one are not propagated
*/
if (databaseName != NULL &&
pg_strcasecmp(databaseName, currentDatabaseName) != 0)
{
return false;
}
/*
* default roles are skipped, because reserved roles
* cannot be altered.
*/
if (roleName != NULL && IsReservedName(roleName))
{
return false;
}
return true;
}

View File

@ -558,14 +558,10 @@ multi_ProcessUtility(PlannedStmt *pstmt,
if (IsA(parsetree, RenameStmt) && ((RenameStmt *) parsetree)->renameType ==
OBJECT_ROLE && EnableAlterRolePropagation)
{
ereport(NOTICE, (errmsg("Citus partially supports ALTER ROLE for "
"distributed databases"),
errdetail(
"Citus does not propagate ALTER ROLE ... RENAME TO "
"commands to workers"),
errhint("You can manually alter roles on workers.")));
ereport(NOTICE, (errmsg("not propagating ALTER ROLE ... RENAME TO commands "
"to worker nodes"),
errhint("Connect to worker nodes directly to manually "
"rename the role")));
}
}

View File

@ -21,6 +21,7 @@
static void AppendAlterRoleStmt(StringInfo buf, AlterRoleStmt *stmt);
static void AppendAlterRoleSetStmt(StringInfo buf, AlterRoleSetStmt *stmt);
static void AppendRoleOption(StringInfo buf, ListCell *optionCell);
/*
@ -75,86 +76,100 @@ AppendAlterRoleStmt(StringInfo buf, AlterRoleStmt *stmt)
foreach(optionCell, stmt->options)
{
DefElem *option = (DefElem *) lfirst(optionCell);
AppendRoleOption(buf, optionCell);
}
}
if (strcmp(option->defname, "superuser") == 0 && intVal(option->arg))
/*
* AppendRoleOption generates the string representation for the role options
* and appends it to the buffer.
*
* This function only generates strings for common role options of ALTER ROLE
* and CREATE ROLE statements. The extra options for CREATE ROLE are handled
* seperately.
*/
static void
AppendRoleOption(StringInfo buf, ListCell *optionCell)
{
DefElem *option = (DefElem *) lfirst(optionCell);
if (strcmp(option->defname, "superuser") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " SUPERUSER");
}
else if (strcmp(option->defname, "superuser") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOSUPERUSER");
}
else if (strcmp(option->defname, "createdb") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " CREATEDB");
}
else if (strcmp(option->defname, "createdb") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOCREATEDB");
}
else if (strcmp(option->defname, "createrole") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " CREATEROLE");
}
else if (strcmp(option->defname, "createrole") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOCREATEROLE");
}
else if (strcmp(option->defname, "inherit") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " INHERIT");
}
else if (strcmp(option->defname, "inherit") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOINHERIT");
}
else if (strcmp(option->defname, "canlogin") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " LOGIN");
}
else if (strcmp(option->defname, "canlogin") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOLOGIN");
}
else if (strcmp(option->defname, "isreplication") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " REPLICATION");
}
else if (strcmp(option->defname, "isreplication") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOREPLICATION");
}
else if (strcmp(option->defname, "bypassrls") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " BYPASSRLS");
}
else if (strcmp(option->defname, "bypassrls") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOBYPASSRLS");
}
else if (strcmp(option->defname, "connectionlimit") == 0)
{
appendStringInfo(buf, " CONNECTION LIMIT %d", intVal(option->arg));
}
else if (strcmp(option->defname, "password") == 0)
{
if (option->arg != NULL)
{
appendStringInfo(buf, " SUPERUSER");
appendStringInfo(buf, " PASSWORD %s", quote_literal_cstr(strVal(
option->arg)));
}
else if (strcmp(option->defname, "superuser") == 0 && !intVal(option->arg))
else
{
appendStringInfo(buf, " NOSUPERUSER");
}
else if (strcmp(option->defname, "createdb") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " CREATEDB");
}
else if (strcmp(option->defname, "createdb") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOCREATEDB");
}
else if (strcmp(option->defname, "createrole") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " CREATEROLE");
}
else if (strcmp(option->defname, "createrole") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOCREATEROLE");
}
else if (strcmp(option->defname, "inherit") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " INHERIT");
}
else if (strcmp(option->defname, "inherit") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOINHERIT");
}
else if (strcmp(option->defname, "canlogin") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " LOGIN");
}
else if (strcmp(option->defname, "canlogin") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOLOGIN");
}
else if (strcmp(option->defname, "isreplication") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " REPLICATION");
}
else if (strcmp(option->defname, "isreplication") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOREPLICATION");
}
else if (strcmp(option->defname, "bypassrls") == 0 && intVal(option->arg))
{
appendStringInfo(buf, " BYPASSRLS");
}
else if (strcmp(option->defname, "bypassrls") == 0 && !intVal(option->arg))
{
appendStringInfo(buf, " NOBYPASSRLS");
}
else if (strcmp(option->defname, "connectionlimit") == 0)
{
appendStringInfo(buf, " CONNECTION LIMIT %d", intVal(option->arg));
}
else if (strcmp(option->defname, "password") == 0)
{
if (option->arg != NULL)
{
appendStringInfo(buf, " PASSWORD %s", quote_literal_cstr(strVal(
option->arg)));
}
else
{
appendStringInfo(buf, " PASSWORD NULL");
}
}
else if (strcmp(option->defname, "validUntil") == 0)
{
appendStringInfo(buf, " VALID UNTIL %s", quote_literal_cstr(strVal(
option->arg)));
appendStringInfo(buf, " PASSWORD NULL");
}
}
else if (strcmp(option->defname, "validUntil") == 0)
{
appendStringInfo(buf, " VALID UNTIL %s", quote_literal_cstr(strVal(option->arg)));
}
}

View File

@ -24,6 +24,7 @@
#include "distributed/listutils.h"
#include "distributed/metadata/dependency.h"
#include "distributed/metadata/distobject.h"
#include "distributed/metadata_cache.h"
#include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
@ -530,6 +531,20 @@ SupportedDependencyByCitus(const ObjectAddress *address)
return true;
}
case OCLASS_ROLE:
{
/*
* Community only supports the extension owner as a distributed object to
* propagate alter statements for this user
*/
if (address->objectId == CitusExtensionOwner())
{
return true;
}
return false;
}
case OCLASS_EXTENSION:
{
return true;

View File

@ -96,6 +96,7 @@ static void InsertNodeRow(int nodeid, char *nodename, int32 nodeport, NodeMetada
static void DeleteNodeRow(char *nodename, int32 nodeport);
static void SetUpDistributedTableDependencies(WorkerNode *workerNode);
static WorkerNode * TupleToWorkerNode(TupleDesc tupleDescriptor, HeapTuple heapTuple);
static void PropagateNodeWideObjects(WorkerNode *newWorkerNode);
static WorkerNode * ModifiableWorkerNode(const char *nodeName, int32 nodePort);
static void UpdateNodeLocation(int32 nodeId, char *newNodeName, int32 newNodePort);
static bool UnsetMetadataSyncedForAll(void);
@ -388,8 +389,22 @@ SetUpDistributedTableDependencies(WorkerNode *newWorkerNode)
if (NodeIsPrimary(newWorkerNode))
{
EnsureNoModificationsHaveBeenDone();
ReplicateAllDependenciesToNode(newWorkerNode->workerName,
newWorkerNode->workerPort);
if (ShouldPropagate())
{
PropagateNodeWideObjects(newWorkerNode);
ReplicateAllDependenciesToNode(newWorkerNode->workerName,
newWorkerNode->workerPort);
}
else
{
ereport(WARNING, (errmsg("citus.enable_object_propagation is off, not "
"creating distributed objects on worker"),
errdetail("distributed objects are only kept in sync when "
"citus.enable_object_propagation is set to on. "
"Newly activated nodes will not get these "
"objects created")));
}
if (ReplicateReferenceTablesOnActivate)
{
@ -413,27 +428,38 @@ SetUpDistributedTableDependencies(WorkerNode *newWorkerNode)
/*
* PropagateRolesToNewNode copies the roles' attributes in the new node. Roles that do
* not exist in the workers are not created and simply skipped.
* PropagateNodeWideObjects is called during node activation to propagate any object that
* should be propagated for every node. These are generally not linked to any distributed
* object but change system wide behaviour.
*/
static void
PropagateRolesToNewNode(WorkerNode *newWorkerNode)
PropagateNodeWideObjects(WorkerNode *newWorkerNode)
{
if (!EnableAlterRolePropagation)
/* collect all commands */
List *ddlCommands = NIL;
if (EnableAlterRoleSetPropagation)
{
return;
/*
* Get commands for database and postgres wide settings. Since these settings are not
* linked to any role that can be distributed we need to distribute them seperately
*/
List *alterRoleSetCommands = GenerateAlterRoleSetCommandForRole(InvalidOid);
ddlCommands = list_concat(ddlCommands, alterRoleSetCommands);
}
List *ddlCommands = NIL;
List *alterRoleCommands = GenerateAlterRoleIfExistsCommandAllRoles();
List *alterRoleSetCommands = GenerateAlterRoleSetIfExistsCommands();
if (list_length(ddlCommands) > 0)
{
/* if there are command wrap them in enable_ddl_propagation off */
ddlCommands = lcons(DISABLE_DDL_PROPAGATION, ddlCommands);
ddlCommands = lappend(ddlCommands, ENABLE_DDL_PROPAGATION);
ddlCommands = list_concat(ddlCommands, alterRoleCommands);
ddlCommands = list_concat(ddlCommands, alterRoleSetCommands);
SendCommandListToWorkerInSingleTransaction(newWorkerNode->workerName,
newWorkerNode->workerPort,
CitusExtensionOwnerName(), ddlCommands);
/* send commands to new workers*/
SendCommandListToWorkerInSingleTransaction(newWorkerNode->workerName,
newWorkerNode->workerPort,
CitusExtensionOwnerName(),
ddlCommands);
}
}
@ -616,7 +642,6 @@ ActivateNode(char *nodeName, int nodePort)
WorkerNode *newWorkerNode = SetNodeState(nodeName, nodePort, isActive);
PropagateRolesToNewNode(newWorkerNode);
SetUpDistributedTableDependencies(newWorkerNode);
return newWorkerNode->nodeId;
}

View File

@ -840,12 +840,23 @@ RegisterCitusConfigVariables(void)
DefineCustomBoolVariable(
"citus.enable_alter_role_propagation",
gettext_noop("Enables propagating role passwords statements to workers"),
gettext_noop("Enables propagating ALTER ROLE statements to workers (excluding "
"ALTER ROLE SET)"),
NULL,
&EnableAlterRolePropagation,
false,
true,
PGC_USERSET,
GUC_STANDARD,
GUC_NO_SHOW_ALL,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"citus.enable_alter_role_set_propagation",
gettext_noop("Enables propagating ALTER ROLE SET statements to workers"),
NULL,
&EnableAlterRoleSetPropagation,
true,
PGC_USERSET,
GUC_NO_SHOW_ALL,
NULL, NULL, NULL);
/*

View File

@ -6,3 +6,11 @@
#include "udfs/update_distributed_table_colocation/9.3-2.sql"
#include "udfs/replicate_reference_tables/9.3-2.sql"
#include "udfs/citus_remote_connection_stats/9.3-2.sql"
#include "udfs/worker_create_or_alter_role/9.3-2.sql"
-- add citus extension owner as a distributed object, if not already in there
INSERT INTO citus.pg_dist_object SELECT
(SELECT oid FROM pg_class WHERE relname = 'pg_authid') AS oid,
(SELECT oid FROM pg_authid WHERE rolname = current_user) as objid,
0 as objsubid
ON CONFLICT DO NOTHING;

View File

@ -0,0 +1,13 @@
CREATE OR REPLACE FUNCTION pg_catalog.worker_create_or_alter_role(
role_name text,
create_role_utility_query text,
alter_role_utility_query text)
RETURNS BOOL
LANGUAGE C
AS 'MODULE_PATHNAME', $$worker_create_or_alter_role$$;
COMMENT ON FUNCTION pg_catalog.worker_create_or_alter_role(
role_name text,
create_role_utility_query text,
alter_role_utility_query text)
IS 'runs the create role query, if the role doesn''t exists, runs the alter role query if it does';

View File

@ -0,0 +1,13 @@
CREATE OR REPLACE FUNCTION pg_catalog.worker_create_or_alter_role(
role_name text,
create_role_utility_query text,
alter_role_utility_query text)
RETURNS BOOL
LANGUAGE C
AS 'MODULE_PATHNAME', $$worker_create_or_alter_role$$;
COMMENT ON FUNCTION pg_catalog.worker_create_or_alter_role(
role_name text,
create_role_utility_query text,
alter_role_utility_query text)
IS 'runs the create role query, if the role doesn''t exists, runs the alter role query if it does';

View File

@ -18,6 +18,7 @@
#include "utils/builtins.h"
PG_FUNCTION_INFO_V1(alter_role_if_exists);
PG_FUNCTION_INFO_V1(worker_create_or_alter_role);
/*
* alter_role_if_exists checks if the role, whose name is given
@ -45,3 +46,90 @@ alter_role_if_exists(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(true);
}
/*
* worker_create_or_alter_role(
* role_name text,
* create_role_utility_query text,
* alter_role_utility_query text)
*
* This UDF checks if the role, whose name is given in role_name exists.
*
* If the role does not exist it will run the query provided in create_role_utility_query
* which is expected to be a CreateRoleStmt. If a different statement is provided the call
* will raise an error,
*
* If the role does exist it will run the query provided in alter_role_utility_query to
* change the existing user in such a way that it is compatible with the user on the
* coordinator. This query is expected to be a AlterRoleStmt, if a different statement is
* provdided the function will raise an error.
*
* For both queries a NULL value can be passed to omit the execution of that condition.
*
* The function returns true if a command has been successfully executed, false if no
* command was executed, and raises an error if something went wrong.
*/
Datum
worker_create_or_alter_role(PG_FUNCTION_ARGS)
{
text *rolenameText = PG_GETARG_TEXT_P(0);
const char *rolename = text_to_cstring(rolenameText);
if (get_role_oid(rolename, true) == InvalidOid)
{
if (PG_ARGISNULL(1))
{
PG_RETURN_BOOL(false);
}
text *createRoleUtilityQueryText = PG_GETARG_TEXT_P(1);
const char *createRoleUtilityQuery = text_to_cstring(createRoleUtilityQueryText);
Node *parseTree = ParseTreeNode(createRoleUtilityQuery);
if (nodeTag(parseTree) != T_CreateRoleStmt)
{
ereport(ERROR, (errmsg("cannot create role"),
errdetail("the role %s does not exist "
"but %s is not a correct CREATE ROLE query",
quote_literal_cstr(rolename),
quote_literal_cstr(createRoleUtilityQuery))));
}
CitusProcessUtility(parseTree,
createRoleUtilityQuery,
PROCESS_UTILITY_TOPLEVEL,
NULL,
None_Receiver, NULL);
PG_RETURN_BOOL(true);
}
else
{
if (PG_ARGISNULL(2))
{
PG_RETURN_BOOL(false);
}
text *alterRoleUtilityQueryText = PG_GETARG_TEXT_P(2);
const char *alterRoleUtilityQuery = text_to_cstring(alterRoleUtilityQueryText);
Node *parseTree = ParseTreeNode(alterRoleUtilityQuery);
if (nodeTag(parseTree) != T_AlterRoleStmt)
{
ereport(ERROR, (errmsg("cannot alter role"),
errdetail("the role %s exists "
"but %s is not a correct alter ROLE query",
quote_literal_cstr(rolename),
quote_literal_cstr(alterRoleUtilityQuery))));
}
CitusProcessUtility(parseTree,
alterRoleUtilityQuery,
PROCESS_UTILITY_TOPLEVEL,
NULL,
None_Receiver, NULL);
PG_RETURN_BOOL(true);
}
}

View File

@ -185,9 +185,12 @@ extern List * PreprocessRenameAttributeStmt(Node *stmt, const char *queryString)
/* role.c - forward declarations*/
extern List * PostprocessAlterRoleStmt(Node *stmt, const char *queryString);
extern List * PreprocessAlterRoleSetStmt(Node *stmt, const char *queryString);
extern List * GenerateAlterRoleIfExistsCommandAllRoles(void);
extern List * GenerateAlterRoleSetIfExistsCommands(void);
extern List * GenerateAlterRoleSetCommandForRole(Oid roleid);
extern ObjectAddress AlterRoleStmtObjectAddress(Node *node,
bool missing_ok);
extern ObjectAddress AlterRoleSetStmtObjectAddress(Node *node,
bool missing_ok);
extern List * GenerateCreateOrAlterRoleCommand(Oid roleOid);
/* schema.c - forward declarations */
extern List * PreprocessDropSchemaStmt(Node *dropSchemaStatement,
@ -268,7 +271,7 @@ extern char * GetFunctionDDLCommand(const RegProcedure funcOid, bool useCreateOr
extern char * GenerateBackupNameForProcCollision(const ObjectAddress *address);
extern ObjectWithArgs * ObjectWithArgsFromOid(Oid funcOid);
/* vacuum.c - froward declarations */
/* vacuum.c - forward declarations */
extern void PostprocessVacuumStmt(VacuumStmt *vacuumStmt, const char *vacuumCommand);
extern bool ShouldPropagateSetCommand(VariableSetStmt *setStmt);

View File

@ -31,6 +31,7 @@ extern bool EnableDDLPropagation;
extern bool EnableDependencyCreation;
extern bool EnableCreateTypePropagation;
extern bool EnableAlterRolePropagation;
extern bool EnableAlterRoleSetPropagation;
/*
* A DDLJob encapsulates the remote tasks and commands needed to process all or

View File

@ -1,202 +1,25 @@
CREATE SCHEMA alter_role;
SET citus.enable_alter_role_propagation to ON;
CREATE ROLE alter_role_1 WITH LOGIN;
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
SELECT run_command_on_workers($$CREATE ROLE alter_role_1 WITH LOGIN;$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
(2 rows)
-- postgres errors out
ALTER ROLE alter_role_1 WITH SUPERUSER NOSUPERUSER;
ERROR: conflicting or redundant options
-- make sure that we propagate all options accurately
ALTER ROLE alter_role_1 WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 66 VALID UNTIL '2032-05-05';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
row
---------------------------------------------------------------------
(alter_role_1,t,t,t,t,t,t,t,66,,2032)
(1 row)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(alter_role_1,t,t,t,t,t,t,t,66,,2032)")
(localhost,57638,t,"(alter_role_1,t,t,t,t,t,t,t,66,,2032)")
(2 rows)
-- make sure that we propagate all options accurately
ALTER ROLE alter_role_1 WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 0 VALID UNTIL '2052-05-05';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
row
---------------------------------------------------------------------
(alter_role_1,f,f,f,f,f,f,f,0,,2052)
(1 row)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(alter_role_1,f,f,f,f,f,f,f,0,,2052)")
(localhost,57638,t,"(alter_role_1,f,f,f,f,f,f,f,0,,2052)")
(2 rows)
-- make sure that non-existent users are handled properly
ALTER ROLE alter_role_2 WITH SUPERUSER NOSUPERUSER;
ERROR: conflicting or redundant options
ALTER ROLE alter_role_2 WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 66 VALID UNTIL '2032-05-05';
ERROR: role "alter_role_2" does not exist
-- make sure that CURRENT_USER just works fine
ALTER ROLE CURRENT_USER WITH CONNECTION LIMIT 123;
SELECT rolconnlimit FROM pg_authid WHERE rolname = CURRENT_USER;
rolconnlimit
---------------------------------------------------------------------
123
(1 row)
SELECT run_command_on_workers($$SELECT rolconnlimit FROM pg_authid WHERE rolname = CURRENT_USER;$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,123)
(localhost,57638,t,123)
(2 rows)
-- make sure that SESSION_USER just works fine
ALTER ROLE SESSION_USER WITH CONNECTION LIMIT 124;
SELECT rolconnlimit FROM pg_authid WHERE rolname = SESSION_USER;
rolconnlimit
---------------------------------------------------------------------
124
(1 row)
SELECT run_command_on_workers($$SELECT rolconnlimit FROM pg_authid WHERE rolname = SESSION_USER;$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,124)
(localhost,57638,t,124)
(2 rows)
-- now lets test the passwords in more detail
ALTER ROLE alter_role_1 WITH PASSWORD NULL;
SELECT rolpassword is NULL FROM pg_authid WHERE rolname = 'alter_role_1';
?column?
---------------------------------------------------------------------
t
(1 row)
SELECT run_command_on_workers($$SELECT rolpassword is NULL FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,t)
(localhost,57638,t,t)
(2 rows)
ALTER ROLE alter_role_1 WITH PASSWORD 'test1';
SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1';
rolpassword
---------------------------------------------------------------------
md52f9cc8d65e37edcc45c4a489bdfc699d
(1 row)
SELECT run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,md52f9cc8d65e37edcc45c4a489bdfc699d)
(localhost,57638,t,md52f9cc8d65e37edcc45c4a489bdfc699d)
(2 rows)
ALTER ROLE alter_role_1 WITH ENCRYPTED PASSWORD 'test2';
SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1';
rolpassword
---------------------------------------------------------------------
md5e17f7818c5ec023fa87bdb97fd3e842e
(1 row)
SELECT run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,md5e17f7818c5ec023fa87bdb97fd3e842e)
(localhost,57638,t,md5e17f7818c5ec023fa87bdb97fd3e842e)
(2 rows)
ALTER ROLE alter_role_1 WITH ENCRYPTED PASSWORD 'md59cce240038b7b335c6aa9674a6f13e72';
SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1';
rolpassword
---------------------------------------------------------------------
md59cce240038b7b335c6aa9674a6f13e72
(1 row)
SELECT run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,md59cce240038b7b335c6aa9674a6f13e72)
(localhost,57638,t,md59cce240038b7b335c6aa9674a6f13e72)
(2 rows)
-- edge case role names
CREATE ROLE "alter_role'1" WITH LOGIN;
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
SELECT run_command_on_workers($$CREATE ROLE "alter_role'1" WITH LOGIN;$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
(2 rows)
ALTER ROLE "alter_role'1" CREATEROLE;
SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role''1';
rolcreaterole
---------------------------------------------------------------------
t
(1 row)
SELECT run_command_on_workers($$SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role''1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,t)
(localhost,57638,t,t)
(2 rows)
CREATE ROLE "alter_role""1" WITH LOGIN;
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
SELECT run_command_on_workers($$CREATE ROLE "alter_role""1" WITH LOGIN;$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
(2 rows)
ALTER ROLE "alter_role""1" CREATEROLE;
SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role"1';
rolcreaterole
---------------------------------------------------------------------
t
(1 row)
SELECT run_command_on_workers($$SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role"1'$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,t)
(localhost,57638,t,t)
(2 rows)
-- add node
ALTER ROLE alter_role_1 WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 66 VALID UNTIL '2032-05-05' PASSWORD 'test3';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
row
---------------------------------------------------------------------
(alter_role_1,t,t,t,t,t,t,t,66,md5ead5c53df946838b1291bba7757f41a7,2032)
(1 row)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
-- test if the passowrd of the extension owner can be upgraded
ALTER ROLE CURRENT_USER PASSWORD 'password123' VALID UNTIL 'infinity';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(alter_role_1,t,t,t,t,t,t,t,66,md5ead5c53df946838b1291bba7757f41a7,2032)")
(localhost,57638,t,"(alter_role_1,t,t,t,t,t,t,t,66,md5ead5c53df946838b1291bba7757f41a7,2032)")
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,-1,md5891d7d5079424b1cb973187d354d78de,Infinity)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,-1,md5891d7d5079424b1cb973187d354d78de,Infinity)")
(2 rows)
-- test if the password and some connection settings are propagated when a node gets added
ALTER ROLE CURRENT_USER WITH CONNECTION LIMIT 66 VALID UNTIL '2032-05-05' PASSWORD 'password456';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
row
---------------------------------------------------------------------
(0 rows)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,66,md568701dc40be546e0357027fb0109338c,2032)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,66,md568701dc40be546e0357027fb0109338c,2032)")
(2 rows)
SELECT master_remove_node('localhost', :worker_1_port);
@ -205,17 +28,16 @@ SELECT master_remove_node('localhost', :worker_1_port);
(1 row)
ALTER ROLE alter_role_1 WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 0 VALID UNTIL '2052-05-05' PASSWORD 'test4';
ALTER ROLE CURRENT_USER WITH CONNECTION LIMIT 0 VALID UNTIL '2052-05-05' PASSWORD 'password789';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
row
row
---------------------------------------------------------------------
(alter_role_1,f,f,f,f,f,f,f,0,md5be308f25c7b1a2d50c85cf7e6f074df9,2052)
(1 row)
(0 rows)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57638,t,"(alter_role_1,f,f,f,f,f,f,f,0,md5be308f25c7b1a2d50c85cf7e6f074df9,2052)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,0,md53e559cc1fcf0c70f1f8e05c9a79c3133,2052)")
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
@ -225,22 +47,91 @@ SELECT 1 FROM master_add_node('localhost', :worker_1_port);
(1 row)
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
row
row
---------------------------------------------------------------------
(alter_role_1,f,f,f,f,f,f,f,0,md5be308f25c7b1a2d50c85cf7e6f074df9,2052)
(1 row)
(0 rows)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
run_command_on_workers
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(alter_role_1,f,f,f,f,f,f,f,0,md5be308f25c7b1a2d50c85cf7e6f074df9,2052)")
(localhost,57638,t,"(alter_role_1,f,f,f,f,f,f,f,0,md5be308f25c7b1a2d50c85cf7e6f074df9,2052)")
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,0,md53e559cc1fcf0c70f1f8e05c9a79c3133,2052)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,0,md53e559cc1fcf0c70f1f8e05c9a79c3133,2052)")
(2 rows)
-- give login permissions so that we can connect and check if the previous queries were propagated
ALTER ROLE alter_role_1 LOGIN CONNECTION LIMIT 10;
-- check user, database and postgres wide SET settings.
-- pre check
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
SELECT run_command_on_workers('SHOW enable_hashagg');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
-- remove 1 node to verify settings are copied when the node gets added back
SELECT master_remove_node('localhost', :worker_1_port);
master_remove_node
---------------------------------------------------------------------
(1 row)
-- change a setting for all users
ALTER ROLE ALL SET enable_hashjoin TO FALSE;
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57638,t,off)
(1 row)
ALTER ROLE ALL IN DATABASE regression SET enable_indexonlyscan TO FALSE;
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57638,t,off)
(1 row)
-- alter configuration_parameter defaults for a user
ALTER ROLE CURRENT_USER SET enable_hashagg TO FALSE;
SELECT run_command_on_workers('SHOW enable_hashagg');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57638,t,off)
(1 row)
-- add worker and check all settings are copied
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
?column?
---------------------------------------------------------------------
1
(1 row)
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,off)
(localhost,57638,t,off)
(2 rows)
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,off)
(localhost,57638,t,off)
(2 rows)
SELECT run_command_on_workers('SHOW enable_hashagg');
run_command_on_workers
---------------------------------------------------------------------
@ -257,18 +148,9 @@ SELECT run_command_on_workers('SHOW enable_hashagg');
(localhost,57638,t,on)
(2 rows)
-- provide role and database names
ALTER ROLE alter_role_1 IN DATABASE regression SET enable_hashjoin TO 0;
SET ROLE alter_role_1;
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,off)
(localhost,57638,t,off)
(2 rows)
-- make sure that only alter_role_1 was affected
RESET ROLE;
-- RESET ALL with IN DATABASE clause
ALTER ROLE ALL RESET ALL;
-- post check 1 - should have settings reset except for database specific settings
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
@ -276,118 +158,72 @@ SELECT run_command_on_workers('SHOW enable_hashjoin');
(localhost,57638,t,on)
(2 rows)
-- RESET ALL with IN DATABASE clause
ALTER ROLE alter_role_1 IN DATABASE regression RESET ALL;
ALTER ROLE alter_role_1 RESET ALL;
ALTER ROLE ALL RESET ALL;
-- FROM CURRENT clauses
SET statement_timeout TO '1min';
ALTER ROLE alter_role_1 SET statement_timeout FROM CURRENT;
SET ROLE alter_role_1;
SELECT run_command_on_workers('SHOW statement_timeout');
run_command_on_workers
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,1min)
(localhost,57638,t,1min)
(localhost,57637,t,off)
(localhost,57638,t,off)
(2 rows)
RESET statement_timeout;
RESET ROLE;
-- the session defaults should be updated on master_add_node
SELECT run_command_on_workers('SHOW enable_hashagg');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
ALTER ROLE ALL IN DATABASE regression RESET ALL;
-- post check 2 - should have all settings reset
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
SELECT run_command_on_workers('SHOW enable_hashagg');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
-- make sure alter role set is not propagated when the feature is deliberately turned off
SET citus.enable_alter_role_set_propagation TO off;
-- remove 1 node to verify settings are NOT copied when the node gets added back
SELECT master_remove_node('localhost', :worker_1_port);
master_remove_node
---------------------------------------------------------------------
(1 row)
ALTER ROLE SESSION_USER SET enable_mergejoin TO false;
ALTER ROLE CURRENT_USER SET statement_timeout TO '2min';
ALTER ROLE CURRENT_USER SET log_min_duration_statement TO '123s';
ALTER ROLE CURRENT_USER SET "app.dev""" TO 'a\nb';
ALTER ROLE CURRENT_USER SET myvar.foobar TO "007";
ALTER ROLE ALL SET enable_hashjoin TO FALSE;
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
?column?
---------------------------------------------------------------------
1
(1 row)
SELECT run_command_on_workers('SHOW enable_mergejoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,off)
(localhost,57638,t,off)
(2 rows)
SELECT run_command_on_workers('SHOW statement_timeout');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,2min)
(localhost,57638,t,2min)
(2 rows)
SELECT run_command_on_workers('SHOW log_min_duration_statement');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,123s)
(localhost,57638,t,123s)
(2 rows)
SELECT run_command_on_workers('SHOW "app.dev"""');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"a\\nb")
(localhost,57638,t,"a\\nb")
(2 rows)
SELECT run_command_on_workers('SHOW myvar.foobar');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,007)
(localhost,57638,t,007)
(2 rows)
-- revert back to defaults
ALTER ROLE SESSION_USER RESET ALL;
SELECT run_command_on_workers('SHOW enable_mergejoin');
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
SELECT run_command_on_workers('SHOW statement_timeout');
ALTER ROLE ALL RESET enable_hashjoin;
SELECT run_command_on_workers('SHOW enable_hashjoin');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,0)
(localhost,57638,t,0)
(localhost,57637,t,on)
(localhost,57638,t,on)
(2 rows)
SELECT run_command_on_workers('SHOW log_min_duration_statement');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,-1)
(localhost,57638,t,-1)
(2 rows)
SELECT run_command_on_workers('SHOW "app.dev"""');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,f,"ERROR: unrecognized configuration parameter ""app.dev""""")
(localhost,57638,f,"ERROR: unrecognized configuration parameter ""app.dev""""")
(2 rows)
SELECT run_command_on_workers('SHOW myvar.foobar');
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,f,"ERROR: unrecognized configuration parameter ""myvar.foobar""")
(localhost,57638,f,"ERROR: unrecognized configuration parameter ""myvar.foobar""")
(2 rows)
-- we don't support propagation of ALTER ROLE ... RENAME TO commands.
ALTER ROLE alter_role_1 RENAME TO alter_role_1_new;
NOTICE: MD5 password cleared because of role rename
NOTICE: Citus partially supports ALTER ROLE for distributed databases
DETAIL: Citus does not propagate ALTER ROLE ... RENAME TO commands to workers
HINT: You can manually alter roles on workers.
SET citus.enable_alter_role_propagation to OFF;
DROP SCHEMA alter_role CASCADE;

View File

@ -176,13 +176,15 @@ SET citus.enable_alter_role_propagation TO ON;
ALTER ROLE role_1 SUPERUSER;
SET citus.enable_alter_role_propagation TO OFF;
SET ROLE role_1;
-- this is only supported on citus enterprise where multiple users can be managed
-- The output of the nspname select below will indicate if the create has been granted
GRANT CREATE ON SCHEMA dist_schema TO CURRENT_USER;
\c - - - :worker_1_port
SELECT nspname, nspacl FROM pg_namespace WHERE nspname IN ('dist_schema', 'another_dist_schema', 'non_dist_schema') ORDER BY nspname;
nspname | nspacl
---------------------------------------------------------------------
another_dist_schema | {postgres=UC/postgres,role_3=UC/postgres}
dist_schema | {postgres=UC/postgres,role_3=UC/postgres,role_1=U*C/postgres}
dist_schema | {postgres=UC/postgres,role_3=UC/postgres,role_1=U*/postgres}
(2 rows)
\c - - - :master_port

View File

@ -1,123 +0,0 @@
Parsed test spec with 2 sessions
starting permutation: s1-enable-propagation s2-enable-propagation s1-begin s1-alter-role-1 s2-add-node s1-commit
run_command_on_workers
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
step s1-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s2-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s1-begin:
BEGIN;
step s1-alter-role-1:
ALTER ROLE alter_role_1 NOSUPERUSER;
step s2-add-node:
SELECT 1 FROM master_add_node('localhost', 57637);
<waiting ...>
step s1-commit:
COMMIT;
step s2-add-node: <... completed>
?column?
1
run_command_on_workers
(localhost,57637,t,"DROP ROLE")
(localhost,57638,t,"DROP ROLE")
starting permutation: s1-enable-propagation s2-enable-propagation s1-begin s1-add-node s2-alter-role-1 s1-commit
run_command_on_workers
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
step s1-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s2-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s1-begin:
BEGIN;
step s1-add-node:
SELECT 1 FROM master_add_node('localhost', 57637);
?column?
1
step s2-alter-role-1:
ALTER ROLE alter_role_1 NOSUPERUSER;
<waiting ...>
step s1-commit:
COMMIT;
step s2-alter-role-1: <... completed>
run_command_on_workers
(localhost,57637,t,"DROP ROLE")
(localhost,57638,t,"DROP ROLE")
starting permutation: s1-enable-propagation s2-enable-propagation s1-begin s1-alter-role-1 s2-alter-role-1 s1-commit
run_command_on_workers
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
step s1-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s2-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s1-begin:
BEGIN;
step s1-alter-role-1:
ALTER ROLE alter_role_1 NOSUPERUSER;
step s2-alter-role-1:
ALTER ROLE alter_role_1 NOSUPERUSER;
<waiting ...>
step s1-commit:
COMMIT;
step s2-alter-role-1: <... completed>
error in steps s1-commit s2-alter-role-1: ERROR: tuple concurrently updated
run_command_on_workers
(localhost,57637,t,"DROP ROLE")
(localhost,57638,t,"DROP ROLE")
starting permutation: s1-enable-propagation s2-enable-propagation s1-begin s1-alter-role-1 s2-alter-role-2 s1-commit
run_command_on_workers
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
step s1-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s2-enable-propagation:
SET citus.enable_alter_role_propagation to ON;
step s1-begin:
BEGIN;
step s1-alter-role-1:
ALTER ROLE alter_role_1 NOSUPERUSER;
step s2-alter-role-2:
ALTER ROLE alter_role_2 NOSUPERUSER;
step s1-commit:
COMMIT;
run_command_on_workers
(localhost,57637,t,"DROP ROLE")
(localhost,57638,t,"DROP ROLE")

View File

@ -12,7 +12,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -24,6 +24,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -53,7 +54,7 @@ step s1-begin:
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -62,11 +63,11 @@ step s2-public-schema:
SET search_path TO public;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
<waiting ...>
step s1-commit:
COMMIT;
@ -82,7 +83,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -90,6 +91,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -129,7 +131,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -141,6 +143,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -170,10 +173,10 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -182,11 +185,11 @@ step s2-public-schema:
SET search_path TO public;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
<waiting ...>
step s1-commit:
COMMIT;
@ -196,7 +199,7 @@ create_distributed_table
step s2-commit:
COMMIT;
COMMIT;
step s2-print-distributed-objects:
-- print an overview of all distributed objects
@ -205,7 +208,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -213,6 +216,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -252,7 +256,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -264,6 +268,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -293,26 +298,26 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s2-public-schema:
SET search_path TO public;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
create_distributed_table
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
<waiting ...>
step s2-commit:
COMMIT;
COMMIT;
step s1-add-worker: <... completed>
?column?
@ -328,7 +333,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -336,6 +341,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -375,7 +381,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -387,6 +393,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -416,7 +423,7 @@ step s1-begin:
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -426,11 +433,11 @@ step s2-create-schema:
SET search_path TO myschema;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
<waiting ...>
step s1-commit:
COMMIT;
@ -446,7 +453,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -454,6 +461,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
count
@ -494,7 +502,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -506,6 +514,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -535,10 +544,10 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -548,11 +557,11 @@ step s2-create-schema:
SET search_path TO myschema;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
<waiting ...>
step s1-commit:
COMMIT;
@ -562,7 +571,7 @@ create_distributed_table
step s2-commit:
COMMIT;
COMMIT;
step s2-print-distributed-objects:
-- print an overview of all distributed objects
@ -571,7 +580,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -579,6 +588,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
count
@ -619,7 +629,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -631,6 +641,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -660,27 +671,27 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s2-create-schema:
CREATE SCHEMA myschema;
SET search_path TO myschema;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
create_distributed_table
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
<waiting ...>
step s2-commit:
COMMIT;
COMMIT;
step s1-add-worker: <... completed>
?column?
@ -696,7 +707,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -704,6 +715,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
count
@ -744,7 +756,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -756,6 +768,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -789,32 +802,32 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s3-begin:
BEGIN;
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
1
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
<waiting ...>
step s3-use-schema:
SET search_path TO myschema;
step s3-create-table:
CREATE TABLE t2 (a int, b int);
CREATE TABLE t2 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t2', 'a');
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t2', 'a');
<waiting ...>
step s1-commit:
COMMIT;
@ -824,14 +837,14 @@ create_distributed_table
step s2-commit:
COMMIT;
COMMIT;
step s3-create-table: <... completed>
create_distributed_table
step s3-commit:
COMMIT;
COMMIT;
step s2-print-distributed-objects:
-- print an overview of all distributed objects
@ -840,7 +853,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -848,6 +861,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
count
@ -888,7 +902,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -900,6 +914,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -926,7 +941,7 @@ master_remove_node
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -936,39 +951,39 @@ step s2-create-schema:
SET search_path TO myschema;
step s2-begin:
BEGIN;
BEGIN;
step s3-begin:
BEGIN;
BEGIN;
step s3-use-schema:
SET search_path TO myschema;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
create_distributed_table
step s3-create-table:
CREATE TABLE t2 (a int, b int);
CREATE TABLE t2 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t2', 'a');
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t2', 'a');
<waiting ...>
step s2-commit:
COMMIT;
COMMIT;
step s3-create-table: <... completed>
create_distributed_table
step s3-commit:
COMMIT;
COMMIT;
step s2-print-distributed-objects:
-- print an overview of all distributed objects
@ -977,7 +992,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -985,6 +1000,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
count
@ -1025,7 +1041,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1037,6 +1053,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1066,13 +1083,13 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s3-begin:
BEGIN;
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -1086,17 +1103,17 @@ step s3-create-schema2:
SET search_path TO myschema2;
step s2-create-table:
CREATE TABLE t1 (a int, b int);
CREATE TABLE t1 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
<waiting ...>
step s3-create-table:
CREATE TABLE t2 (a int, b int);
CREATE TABLE t2 (a int, b int);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t2', 'a');
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t2', 'a');
<waiting ...>
step s1-commit:
COMMIT;
@ -1110,10 +1127,10 @@ create_distributed_table
step s3-commit:
COMMIT;
COMMIT;
step s2-commit:
COMMIT;
COMMIT;
step s2-print-distributed-objects:
-- print an overview of all distributed objects
@ -1122,7 +1139,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1130,6 +1147,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{myschema2},{})
(schema,{public},{})
@ -1171,7 +1189,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1183,6 +1201,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1212,7 +1231,7 @@ step s1-begin:
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -1221,7 +1240,7 @@ step s2-public-schema:
SET search_path TO public;
step s2-create-type:
CREATE TYPE tt1 AS (a int, b int);
CREATE TYPE tt1 AS (a int, b int);
<waiting ...>
step s1-commit:
COMMIT;
@ -1234,7 +1253,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1242,6 +1261,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
(type,{public.tt1},{})
count
@ -1282,7 +1302,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1294,6 +1314,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1326,10 +1347,10 @@ step s2-public-schema:
SET search_path TO public;
step s2-create-type:
CREATE TYPE tt1 AS (a int, b int);
CREATE TYPE tt1 AS (a int, b int);
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -1344,7 +1365,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1352,6 +1373,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
(type,{public.tt1},{})
count
@ -1392,7 +1414,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1404,6 +1426,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1433,30 +1456,30 @@ step s1-begin:
BEGIN;
step s2-begin:
BEGIN;
BEGIN;
step s2-create-schema:
CREATE SCHEMA myschema;
SET search_path TO myschema;
step s2-create-type:
CREATE TYPE tt1 AS (a int, b int);
CREATE TYPE tt1 AS (a int, b int);
step s2-create-table-with-type:
CREATE TABLE t1 (a int, b tt1);
CREATE TABLE t1 (a int, b tt1);
-- session needs to have replication factor set to 1, can't do in setup
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
SET citus.replication_model TO 'streaming';
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('t1', 'a');
create_distributed_table
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
<waiting ...>
step s2-commit:
COMMIT;
COMMIT;
step s1-add-worker: <... completed>
?column?
@ -1472,7 +1495,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1480,6 +1503,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
(type,{myschema.tt1},{})
@ -1521,7 +1545,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1533,6 +1557,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1562,7 +1587,7 @@ step s1-begin:
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -1582,10 +1607,10 @@ create_distributed_function
step s2-begin:
BEGIN;
BEGIN;
step s2-commit:
COMMIT;
COMMIT;
step s3-wait-for-metadata-sync:
SELECT public.wait_until_metadata_sync(5000);
@ -1600,7 +1625,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1609,6 +1634,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(function,"{public,add}","{integer,integer}")
(role,{postgres},{})
(schema,{public},{})
count
@ -1648,7 +1674,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1660,6 +1686,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1699,10 +1726,10 @@ create_distributed_function
step s2-begin:
BEGIN;
BEGIN;
step s2-commit:
COMMIT;
COMMIT;
step s3-wait-for-metadata-sync:
SELECT public.wait_until_metadata_sync(5000);
@ -1711,7 +1738,7 @@ wait_until_metadata_sync
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -1732,7 +1759,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1741,6 +1768,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(function,"{public,add}","{integer,integer}")
(role,{postgres},{})
(schema,{public},{})
count
@ -1780,7 +1808,7 @@ step s1-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1792,6 +1820,7 @@ step s1-print-distributed-objects:
1
pg_identify_object_as_address
(role,{postgres},{})
(schema,{public},{})
count
@ -1818,7 +1847,7 @@ master_remove_node
step s2-begin:
BEGIN;
BEGIN;
step s2-create-schema:
CREATE SCHEMA myschema;
@ -1832,7 +1861,7 @@ create_distributed_function
step s2-commit:
COMMIT;
COMMIT;
step s3-wait-for-metadata-sync:
SELECT public.wait_until_metadata_sync(5000);
@ -1844,7 +1873,7 @@ step s1-begin:
BEGIN;
step s1-add-worker:
SELECT 1 FROM master_add_node('localhost', 57638);
SELECT 1 FROM master_add_node('localhost', 57638);
?column?
@ -1865,7 +1894,7 @@ step s2-print-distributed-objects:
SELECT count(*) FROM pg_namespace where nspname = 'myschema';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_namespace where nspname = 'myschema';$$);
-- print if the type has been created
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT count(*) FROM pg_type where typname = 'tt1';
SELECT run_command_on_workers($$SELECT count(*) FROM pg_type where typname = 'tt1';$$);
-- print if the function has been created
SELECT count(*) FROM pg_proc WHERE proname='add';
@ -1874,6 +1903,7 @@ step s2-print-distributed-objects:
pg_identify_object_as_address
(function,"{myschema,add}","{integer,integer}")
(role,{postgres},{})
(schema,{myschema},{})
(schema,{public},{})
count

View File

@ -26,7 +26,7 @@ step s1-print:
count
2
3
extname extversion nspname
seg 1.1 public
@ -73,7 +73,7 @@ step s1-print:
count
2
3
extname extversion nspname
seg 1.2 public
@ -126,7 +126,7 @@ step s1-print:
count
1
2
extname extversion nspname
run_command_on_workers
@ -168,7 +168,7 @@ step s1-print:
count
3
4
extname extversion nspname
seg 1.3 schema1
@ -215,7 +215,7 @@ step s1-print:
count
2
3
extname extversion nspname
run_command_on_workers
@ -270,7 +270,7 @@ step s1-print:
count
5
6
extname extversion nspname
seg 1.3 schema3
@ -322,7 +322,7 @@ step s1-print:
count
5
6
extname extversion nspname
seg 1.3 schema1
@ -379,7 +379,7 @@ step s1-print:
count
4
5
extname extversion nspname
seg 1.1 public
@ -444,7 +444,7 @@ step s1-print:
count
5
6
extname extversion nspname
seg 1.2 public
@ -497,7 +497,7 @@ step s1-print:
count
4
5
extname extversion nspname
run_command_on_workers
@ -538,7 +538,7 @@ step s1-print:
count
4
5
extname extversion nspname
seg 1.3 schema1
@ -597,7 +597,7 @@ step s1-print:
count
5
6
extname extversion nspname
seg 1.3 schema2
@ -648,7 +648,7 @@ step s1-print:
count
4
5
extname extversion nspname
seg 1.1 public
@ -709,7 +709,7 @@ step s1-print:
count
4
5
extname extversion nspname
run_command_on_workers

View File

@ -1,5 +1,6 @@
SET citus.next_shard_id TO 1220000;
ALTER SEQUENCE pg_catalog.pg_dist_colocationid_seq RESTART 1390000;
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
-- Tests functions related to cluster membership
-- before starting the test, lets try to create reference table and see a
-- meaningful error
@ -9,12 +10,16 @@ ERROR: cannot create reference table "test_reference_table"
DETAIL: There are no active worker nodes.
-- add the nodes to the cluster
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -59,6 +64,8 @@ SELECT master_get_active_worker_nodes();
-- try to disable a node with no placements see that node is removed
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -80,6 +87,8 @@ SELECT master_get_active_worker_nodes();
SET citus.shard_count TO 16;
SET citus.shard_replication_factor TO 1;
SELECT * FROM master_activate_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
master_activate_node
---------------------------------------------------------------------
3
@ -169,6 +178,7 @@ SELECT master_update_node(nodeid, 'localhost', :worker_2_port + 3) FROM pg_dist_
ERROR: permission denied for function master_update_node
-- try to manipulate node metadata via privileged user
SET ROLE node_metadata_user;
SET citus.enable_object_propagation TO off; -- prevent master activate node to actually connect for this test
BEGIN;
SELECT 1 FROM master_add_inactive_node('localhost', :worker_2_port + 1);
?column?
@ -177,6 +187,8 @@ SELECT 1 FROM master_add_inactive_node('localhost', :worker_2_port + 1);
(1 row)
SELECT 1 FROM master_activate_node('localhost', :worker_2_port + 1);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -195,6 +207,8 @@ SELECT 1 FROM master_remove_node('localhost', :worker_2_port + 1);
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port + 1);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -224,6 +238,7 @@ SELECT nodename, nodeport, noderole FROM pg_dist_node ORDER BY nodeport;
ABORT;
\c - postgres - :master_port
SET citus.next_shard_id TO 1220016;
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
SELECT master_get_active_worker_nodes();
master_get_active_worker_nodes
---------------------------------------------------------------------
@ -232,6 +247,8 @@ SELECT master_get_active_worker_nodes();
-- restore the node for next tests
SELECT * FROM master_activate_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
master_activate_node
---------------------------------------------------------------------
3
@ -349,6 +366,8 @@ SELECT * FROM cluster_management_test;
ERROR: there is a shard placement in node group 3 but there are no nodes in that group
-- clean-up
SELECT master_add_node('localhost', :worker_2_port) AS new_node \gset
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
SELECT groupid AS new_group FROM pg_dist_node WHERE nodeid = :new_node \gset
UPDATE pg_dist_placement SET groupid = :new_group WHERE groupid = :worker_2_group;
-- test that you are allowed to remove secondary nodes even if there are placements
@ -382,6 +401,8 @@ SELECT start_metadata_sync_to_node('localhost', :worker_1_port);
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -408,6 +429,7 @@ SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodep
(0 rows)
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
-- check that added nodes are not propagated to nodes without metadata
SELECT stop_metadata_sync_to_node('localhost', :worker_1_port);
stop_metadata_sync_to_node
@ -416,6 +438,8 @@ SELECT stop_metadata_sync_to_node('localhost', :worker_1_port);
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -428,6 +452,7 @@ SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodep
(0 rows)
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
-- check that removing two nodes in the same transaction works
SELECT
master_remove_node('localhost', :worker_1_port),
@ -447,6 +472,10 @@ SELECT count(1) FROM pg_dist_node;
SELECT
master_add_node('localhost', :worker_1_port),
master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
master_add_node | master_add_node
---------------------------------------------------------------------
11 | 12
@ -468,6 +497,8 @@ SELECT master_remove_node('localhost', :worker_2_port);
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -493,6 +524,8 @@ SELECT start_metadata_sync_to_node('localhost', :worker_1_port);
BEGIN;
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -505,6 +538,8 @@ SELECT master_remove_node('localhost', :worker_2_port);
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -525,6 +560,7 @@ SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodep
(1 row)
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
SELECT master_remove_node(nodename, nodeport) FROM pg_dist_node;
master_remove_node
---------------------------------------------------------------------
@ -533,12 +569,16 @@ SELECT master_remove_node(nodename, nodeport) FROM pg_dist_node;
(2 rows)
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -554,6 +594,8 @@ SELECT master_remove_node('localhost', :worker_2_port);
BEGIN;
SELECT 1 FROM master_add_node('localhost', :worker_2_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
?column?
---------------------------------------------------------------------
1
@ -596,6 +638,7 @@ DELETE FROM pg_dist_shard;
DELETE FROM pg_dist_placement;
DELETE FROM pg_dist_node;
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
SELECT stop_metadata_sync_to_node('localhost', :worker_1_port);
stop_metadata_sync_to_node
---------------------------------------------------------------------

View File

@ -367,7 +367,10 @@ HINT: You can manually create a database and its extensions on workers.
\c - - - :master_port
\c another
CREATE EXTENSION citus;
SET citus.enable_object_propagation TO off; -- prevent distributed transactions during add node
SELECT FROM master_add_node('localhost', :worker_1_port);
WARNING: citus.enable_object_propagation is off, not creating distributed objects on worker
DETAIL: distributed objects are only kept in sync when citus.enable_object_propagation is set to on. Newly activated nodes will not get these objects created
--
(1 row)

View File

@ -1173,6 +1173,7 @@ SELECT create_distributed_table('numbers_hash_failure_test', 'key');
-- and rename the existing user
\c - :default_user - :worker_1_port
ALTER USER test_user RENAME TO test_user_new;
NOTICE: not propagating ALTER ROLE ... RENAME TO commands to worker nodes
-- connect back to master and query the reference table
\c - test_user - :master_port
-- should fail since the worker doesn't have test_user anymore
@ -1307,6 +1308,7 @@ WARNING: connection error: localhost:xxxxx
-- break the other node as well
\c - :default_user - :worker_2_port
ALTER USER test_user RENAME TO test_user_new;
NOTICE: not propagating ALTER ROLE ... RENAME TO commands to worker nodes
\c - test_user - :master_port
-- fails on all shard placements
INSERT INTO numbers_hash_failure_test VALUES (2,2);

View File

@ -15,6 +15,7 @@ SELECT run_command_on_workers('CREATE USER reprefuser WITH LOGIN');
(2 rows)
SET citus.enable_alter_role_propagation TO ON;
-- alter role for other than the extension owner works in enterprise, output differs accordingly
ALTER ROLE reprefuser WITH CREATEDB;
SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0);
?column?
@ -50,14 +51,14 @@ ALTER ROLE reprefuser WITH CREATEROLE;
select rolcreatedb, rolcreaterole from pg_roles where rolname = 'reprefuser';
rolcreatedb | rolcreaterole
---------------------------------------------------------------------
t | t
f | t
(1 row)
\c - - - :worker_2_port
select rolcreatedb, rolcreaterole from pg_roles where rolname = 'reprefuser';
rolcreatedb | rolcreaterole
---------------------------------------------------------------------
t | f
f | f
(1 row)
\c - - - :master_port

View File

@ -25,9 +25,10 @@ SELECT i.* FROM citus.pg_dist_object, pg_identify_object_as_address(classid, obj
type | object_names | object_args
---------------------------------------------------------------------
extension | {isn} | {}
role | {postgres} | {}
schema | {fooschema} | {}
schema | {new_schema} | {}
schema | {public} | {}
type | {fooschema.footype} | {}
(5 rows)
(6 rows)

View File

@ -29,7 +29,6 @@ test: isolation_drop_shards isolation_copy_placement_vs_modification
test: isolation_insert_vs_vacuum isolation_transaction_recovery
test: isolation_progress_monitoring
test: isolation_dump_local_wait_edges
test: isolation_alter_role_propagation
test: isolation_replace_wait_function
test: isolation_distributed_deadlock_detection

View File

@ -1,75 +0,0 @@
setup
{
CREATE ROLE alter_role_1 WITH LOGIN;
SELECT run_command_on_workers($$CREATE ROLE alter_role_1 WITH LOGIN;$$);
CREATE ROLE alter_role_2 WITH LOGIN;
SELECT run_command_on_workers($$CREATE ROLE alter_role_2 WITH LOGIN;$$);
}
teardown
{
DROP ROLE IF EXISTS alter_role_1;
SELECT run_command_on_workers($$DROP ROLE IF EXISTS alter_role_1;$$);
DROP ROLE IF EXISTS alter_role_2;
SELECT run_command_on_workers($$DROP ROLE IF EXISTS alter_role_2;$$);
}
session "s1"
step "s1-enable-propagation"
{
SET citus.enable_alter_role_propagation to ON;
}
step "s1-begin"
{
BEGIN;
}
step "s1-alter-role-1"
{
ALTER ROLE alter_role_1 NOSUPERUSER;
}
step "s1-add-node"
{
SELECT 1 FROM master_add_node('localhost', 57637);
}
step "s1-commit"
{
COMMIT;
}
session "s2"
step "s2-enable-propagation"
{
SET citus.enable_alter_role_propagation to ON;
}
step "s2-alter-role-1"
{
ALTER ROLE alter_role_1 NOSUPERUSER;
}
step "s2-alter-role-2"
{
ALTER ROLE alter_role_2 NOSUPERUSER;
}
step "s2-add-node"
{
SELECT 1 FROM master_add_node('localhost', 57637);
}
permutation "s1-enable-propagation" "s2-enable-propagation" "s1-begin" "s1-alter-role-1" "s2-add-node" "s1-commit"
permutation "s1-enable-propagation" "s2-enable-propagation" "s1-begin" "s1-add-node" "s2-alter-role-1" "s1-commit"
permutation "s1-enable-propagation" "s2-enable-propagation" "s1-begin" "s1-alter-role-1" "s2-alter-role-1" "s1-commit"
permutation "s1-enable-propagation" "s2-enable-propagation" "s1-begin" "s1-alter-role-1" "s2-alter-role-2" "s1-commit"

View File

@ -1,146 +1,73 @@
CREATE SCHEMA alter_role;
SET citus.enable_alter_role_propagation to ON;
-- test if the passowrd of the extension owner can be upgraded
ALTER ROLE CURRENT_USER PASSWORD 'password123' VALID UNTIL 'infinity';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
CREATE ROLE alter_role_1 WITH LOGIN;
SELECT run_command_on_workers($$CREATE ROLE alter_role_1 WITH LOGIN;$$);
-- postgres errors out
ALTER ROLE alter_role_1 WITH SUPERUSER NOSUPERUSER;
-- make sure that we propagate all options accurately
ALTER ROLE alter_role_1 WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 66 VALID UNTIL '2032-05-05';
-- test if the password and some connection settings are propagated when a node gets added
ALTER ROLE CURRENT_USER WITH CONNECTION LIMIT 66 VALID UNTIL '2032-05-05' PASSWORD 'password456';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
-- make sure that we propagate all options accurately
ALTER ROLE alter_role_1 WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 0 VALID UNTIL '2052-05-05';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
-- make sure that non-existent users are handled properly
ALTER ROLE alter_role_2 WITH SUPERUSER NOSUPERUSER;
ALTER ROLE alter_role_2 WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 66 VALID UNTIL '2032-05-05';
-- make sure that CURRENT_USER just works fine
ALTER ROLE CURRENT_USER WITH CONNECTION LIMIT 123;
SELECT rolconnlimit FROM pg_authid WHERE rolname = CURRENT_USER;
SELECT run_command_on_workers($$SELECT rolconnlimit FROM pg_authid WHERE rolname = CURRENT_USER;$$);
-- make sure that SESSION_USER just works fine
ALTER ROLE SESSION_USER WITH CONNECTION LIMIT 124;
SELECT rolconnlimit FROM pg_authid WHERE rolname = SESSION_USER;
SELECT run_command_on_workers($$SELECT rolconnlimit FROM pg_authid WHERE rolname = SESSION_USER;$$);
-- now lets test the passwords in more detail
ALTER ROLE alter_role_1 WITH PASSWORD NULL;
SELECT rolpassword is NULL FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT rolpassword is NULL FROM pg_authid WHERE rolname = 'alter_role_1'$$);
ALTER ROLE alter_role_1 WITH PASSWORD 'test1';
SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1'$$);
ALTER ROLE alter_role_1 WITH ENCRYPTED PASSWORD 'test2';
SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1'$$);
ALTER ROLE alter_role_1 WITH ENCRYPTED PASSWORD 'md59cce240038b7b335c6aa9674a6f13e72';
SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = 'alter_role_1'$$);
-- edge case role names
CREATE ROLE "alter_role'1" WITH LOGIN;
SELECT run_command_on_workers($$CREATE ROLE "alter_role'1" WITH LOGIN;$$);
ALTER ROLE "alter_role'1" CREATEROLE;
SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role''1';
SELECT run_command_on_workers($$SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role''1'$$);
CREATE ROLE "alter_role""1" WITH LOGIN;
SELECT run_command_on_workers($$CREATE ROLE "alter_role""1" WITH LOGIN;$$);
ALTER ROLE "alter_role""1" CREATEROLE;
SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role"1';
SELECT run_command_on_workers($$SELECT rolcreaterole FROM pg_authid WHERE rolname = 'alter_role"1'$$);
-- add node
ALTER ROLE alter_role_1 WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 66 VALID UNTIL '2032-05-05' PASSWORD 'test3';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
SELECT master_remove_node('localhost', :worker_1_port);
ALTER ROLE alter_role_1 WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 0 VALID UNTIL '2052-05-05' PASSWORD 'test4';
ALTER ROLE CURRENT_USER WITH CONNECTION LIMIT 0 VALID UNTIL '2052-05-05' PASSWORD 'password789';
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = 'alter_role_1'$$);
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
-- check user, database and postgres wide SET settings.
-- pre check
SELECT run_command_on_workers('SHOW enable_hashjoin');
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
SELECT run_command_on_workers('SHOW enable_hashagg');
-- give login permissions so that we can connect and check if the previous queries were propagated
ALTER ROLE alter_role_1 LOGIN CONNECTION LIMIT 10;
-- remove 1 node to verify settings are copied when the node gets added back
SELECT master_remove_node('localhost', :worker_1_port);
-- change a setting for all users
ALTER ROLE ALL SET enable_hashjoin TO FALSE;
SELECT run_command_on_workers('SHOW enable_hashjoin');
ALTER ROLE ALL IN DATABASE regression SET enable_indexonlyscan TO FALSE;
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
-- alter configuration_parameter defaults for a user
ALTER ROLE CURRENT_USER SET enable_hashagg TO FALSE;
SELECT run_command_on_workers('SHOW enable_hashagg');
-- add worker and check all settings are copied
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
SELECT run_command_on_workers('SHOW enable_hashjoin');
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
SELECT run_command_on_workers('SHOW enable_hashagg');
-- reset to default values
ALTER ROLE CURRENT_USER RESET enable_hashagg;
SELECT run_command_on_workers('SHOW enable_hashagg');
-- provide role and database names
ALTER ROLE alter_role_1 IN DATABASE regression SET enable_hashjoin TO 0;
SET ROLE alter_role_1;
SELECT run_command_on_workers('SHOW enable_hashjoin');
-- make sure that only alter_role_1 was affected
RESET ROLE;
SELECT run_command_on_workers('SHOW enable_hashjoin');
-- RESET ALL with IN DATABASE clause
ALTER ROLE alter_role_1 IN DATABASE regression RESET ALL;
ALTER ROLE alter_role_1 RESET ALL;
ALTER ROLE ALL RESET ALL;
-- FROM CURRENT clauses
SET statement_timeout TO '1min';
ALTER ROLE alter_role_1 SET statement_timeout FROM CURRENT;
-- post check 1 - should have settings reset except for database specific settings
SELECT run_command_on_workers('SHOW enable_hashjoin');
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
SELECT run_command_on_workers('SHOW enable_hashagg');
SET ROLE alter_role_1;
SELECT run_command_on_workers('SHOW statement_timeout');
ALTER ROLE ALL IN DATABASE regression RESET ALL;
RESET statement_timeout;
RESET ROLE;
-- post check 2 - should have all settings reset
SELECT run_command_on_workers('SHOW enable_hashjoin');
SELECT run_command_on_workers('SHOW enable_indexonlyscan');
SELECT run_command_on_workers('SHOW enable_hashagg');
-- the session defaults should be updated on master_add_node
-- make sure alter role set is not propagated when the feature is deliberately turned off
SET citus.enable_alter_role_set_propagation TO off;
-- remove 1 node to verify settings are NOT copied when the node gets added back
SELECT master_remove_node('localhost', :worker_1_port);
ALTER ROLE SESSION_USER SET enable_mergejoin TO false;
ALTER ROLE CURRENT_USER SET statement_timeout TO '2min';
ALTER ROLE CURRENT_USER SET log_min_duration_statement TO '123s';
ALTER ROLE CURRENT_USER SET "app.dev""" TO 'a\nb';
ALTER ROLE CURRENT_USER SET myvar.foobar TO "007";
ALTER ROLE ALL SET enable_hashjoin TO FALSE;
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
SELECT run_command_on_workers('SHOW enable_mergejoin');
SELECT run_command_on_workers('SHOW statement_timeout');
SELECT run_command_on_workers('SHOW log_min_duration_statement');
SELECT run_command_on_workers('SHOW "app.dev"""');
SELECT run_command_on_workers('SHOW myvar.foobar');
-- revert back to defaults
ALTER ROLE SESSION_USER RESET ALL;
SELECT run_command_on_workers('SHOW enable_mergejoin');
SELECT run_command_on_workers('SHOW statement_timeout');
SELECT run_command_on_workers('SHOW log_min_duration_statement');
SELECT run_command_on_workers('SHOW "app.dev"""');
SELECT run_command_on_workers('SHOW myvar.foobar');
-- we don't support propagation of ALTER ROLE ... RENAME TO commands.
ALTER ROLE alter_role_1 RENAME TO alter_role_1_new;
SET citus.enable_alter_role_propagation to OFF;
SELECT run_command_on_workers('SHOW enable_hashjoin');
ALTER ROLE ALL RESET enable_hashjoin;
SELECT run_command_on_workers('SHOW enable_hashjoin');
DROP SCHEMA alter_role CASCADE;

View File

@ -77,6 +77,8 @@ SET citus.enable_alter_role_propagation TO ON;
ALTER ROLE role_1 SUPERUSER;
SET citus.enable_alter_role_propagation TO OFF;
SET ROLE role_1;
-- this is only supported on citus enterprise where multiple users can be managed
-- The output of the nspname select below will indicate if the create has been granted
GRANT CREATE ON SCHEMA dist_schema TO CURRENT_USER;
\c - - - :worker_1_port
SELECT nspname, nspacl FROM pg_namespace WHERE nspname IN ('dist_schema', 'another_dist_schema', 'non_dist_schema') ORDER BY nspname;

View File

@ -1,5 +1,6 @@
SET citus.next_shard_id TO 1220000;
ALTER SEQUENCE pg_catalog.pg_dist_colocationid_seq RESTART 1390000;
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
-- Tests functions related to cluster membership
@ -83,6 +84,7 @@ SELECT master_update_node(nodeid, 'localhost', :worker_2_port + 3) FROM pg_dist_
-- try to manipulate node metadata via privileged user
SET ROLE node_metadata_user;
SET citus.enable_object_propagation TO off; -- prevent master activate node to actually connect for this test
BEGIN;
SELECT 1 FROM master_add_inactive_node('localhost', :worker_2_port + 1);
SELECT 1 FROM master_activate_node('localhost', :worker_2_port + 1);
@ -96,6 +98,7 @@ ABORT;
\c - postgres - :master_port
SET citus.next_shard_id TO 1220016;
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
SELECT master_get_active_worker_nodes();
-- restore the node for next tests
@ -165,6 +168,7 @@ SELECT master_remove_node('localhost', :worker_2_port);
\c - - - :worker_1_port
SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodeport=:worker_2_port;
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
-- check that added nodes are not propagated to nodes without metadata
SELECT stop_metadata_sync_to_node('localhost', :worker_1_port);
@ -172,6 +176,7 @@ SELECT 1 FROM master_add_node('localhost', :worker_2_port);
\c - - - :worker_1_port
SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodeport=:worker_2_port;
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
-- check that removing two nodes in the same transaction works
SELECT
@ -206,6 +211,7 @@ SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodep
\c - - - :worker_1_port
SELECT nodename, nodeport FROM pg_dist_node WHERE nodename='localhost' AND nodeport=:worker_2_port;
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
SELECT master_remove_node(nodename, nodeport) FROM pg_dist_node;
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
@ -242,6 +248,7 @@ DELETE FROM pg_dist_shard;
DELETE FROM pg_dist_placement;
DELETE FROM pg_dist_node;
\c - - - :master_port
SET citus.enable_object_propagation TO off; -- prevent object propagation on add node during setup
SELECT stop_metadata_sync_to_node('localhost', :worker_1_port);
SELECT stop_metadata_sync_to_node('localhost', :worker_2_port);

View File

@ -332,6 +332,7 @@ CREATE DATABASE another;
\c another
CREATE EXTENSION citus;
SET citus.enable_object_propagation TO off; -- prevent distributed transactions during add node
SELECT FROM master_add_node('localhost', :worker_1_port);
\c - - - :worker_1_port

View File

@ -10,6 +10,7 @@ SET client_min_messages TO WARNING;
CREATE USER reprefuser WITH LOGIN;
SELECT run_command_on_workers('CREATE USER reprefuser WITH LOGIN');
SET citus.enable_alter_role_propagation TO ON;
-- alter role for other than the extension owner works in enterprise, output differs accordingly
ALTER ROLE reprefuser WITH CREATEDB;
SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0);

View File

@ -85,7 +85,6 @@ SELECT nodeid, hasmetadata, metadatasynced FROM pg_dist_node;
--------------------------------------------------------------------------
-- Test updating a node when another node is in readonly-mode
--------------------------------------------------------------------------
SELECT master_add_node('localhost', :worker_2_port) AS nodeid_2 \gset
SELECT 1 FROM start_metadata_sync_to_node('localhost', :worker_2_port);