Skip to content

Commit 181b8ab

Browse files
gurkanindibayJelteFonurctirtir
authored
Adds additional alter database propagation support (#7253)
DESCRIPTION: Adds database connection limit, rename and set tablespace propagation In this PR, below statement propagations are added alter database <database_name> with allow_connections = <boolean_value>; alter database <database_name> rename to <database_name2>; alter database <database_name> set TABLESPACE <table_space_name> --------- Co-authored-by: Jelte Fennema-Nio <[email protected]> Co-authored-by: Jelte Fennema-Nio <[email protected]> Co-authored-by: Onur Tirtir <[email protected]>
1 parent b877d60 commit 181b8ab

File tree

9 files changed

+323
-87
lines changed

9 files changed

+323
-87
lines changed

src/backend/distributed/commands/database.c

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,25 @@ PreprocessGrantOnDatabaseStmt(Node *node, const char *queryString,
192192
}
193193

194194

195+
/*
196+
* IsSetTablespaceStatement returns true if the statement is a SET TABLESPACE statement,
197+
* false otherwise.
198+
*/
199+
static bool
200+
IsSetTablespaceStatement(AlterDatabaseStmt *stmt)
201+
{
202+
DefElem *def = NULL;
203+
foreach_ptr(def, stmt->options)
204+
{
205+
if (strcmp(def->defname, "tablespace") == 0)
206+
{
207+
return true;
208+
}
209+
}
210+
return false;
211+
}
212+
213+
195214
/*
196215
* PreprocessAlterDatabaseStmt is executed before the statement is applied to the local
197216
* postgres instance.
@@ -203,22 +222,38 @@ List *
203222
PreprocessAlterDatabaseStmt(Node *node, const char *queryString,
204223
ProcessUtilityContext processUtilityContext)
205224
{
206-
if (!ShouldPropagate())
225+
bool missingOk = false;
226+
AlterDatabaseStmt *stmt = castNode(AlterDatabaseStmt, node);
227+
ObjectAddress *dbAddress = GetDatabaseAddressFromDatabaseName(stmt->dbname,
228+
missingOk);
229+
230+
if (!ShouldPropagate() || !IsAnyObjectDistributed(list_make1(dbAddress)))
207231
{
208232
return NIL;
209233
}
210234

211-
AlterDatabaseStmt *stmt = castNode(AlterDatabaseStmt, node);
212-
213235
EnsureCoordinator();
214236

215237
char *sql = DeparseTreeNode((Node *) stmt);
216238

217239
List *commands = list_make3(DISABLE_DDL_PROPAGATION,
218-
(void *) sql,
240+
sql,
219241
ENABLE_DDL_PROPAGATION);
220242

221-
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands);
243+
if (IsSetTablespaceStatement(stmt))
244+
{
245+
/*
246+
* Set tablespace does not work inside a transaction.Therefore, we need to use
247+
* NontransactionalNodeDDLTask to run the command on the workers outside
248+
* the transaction block.
249+
*/
250+
251+
return NontransactionalNodeDDLTaskList(NON_COORDINATOR_NODES, commands);
252+
}
253+
else
254+
{
255+
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands);
256+
}
222257
}
223258

224259

@@ -256,6 +291,36 @@ PreprocessAlterDatabaseRefreshCollStmt(Node *node, const char *queryString,
256291

257292
#endif
258293

294+
/*
295+
* PreprocessAlterDatabaseRenameStmt is executed before the statement is applied to the local
296+
* postgres instance. In this stage we prepare ALTER DATABASE RENAME statement to be run on
297+
* all workers.
298+
*/
299+
List *
300+
PostprocessAlterDatabaseRenameStmt(Node *node, const char *queryString)
301+
{
302+
bool missingOk = false;
303+
RenameStmt *stmt = castNode(RenameStmt, node);
304+
ObjectAddress *dbAddress = GetDatabaseAddressFromDatabaseName(stmt->newname,
305+
missingOk);
306+
307+
if (!ShouldPropagate() || !IsAnyObjectDistributed(list_make1(dbAddress)))
308+
{
309+
return NIL;
310+
}
311+
312+
EnsureCoordinator();
313+
314+
char *sql = DeparseTreeNode((Node *) stmt);
315+
316+
List *commands = list_make3(DISABLE_DDL_PROPAGATION,
317+
(void *) sql,
318+
ENABLE_DDL_PROPAGATION);
319+
320+
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands);
321+
}
322+
323+
259324
/*
260325
* PreprocessAlterDatabaseSetStmt is executed before the statement is applied to the local
261326
* postgres instance.

src/backend/distributed/commands/distribute_object_ops.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,16 @@ static DistributeObjectOps Database_Set = {
522522
.markDistributed = false,
523523
};
524524

525+
static DistributeObjectOps Database_Rename = {
526+
.deparse = DeparseAlterDatabaseRenameStmt,
527+
.qualify = NULL,
528+
.preprocess = NULL,
529+
.postprocess = PostprocessAlterDatabaseRenameStmt,
530+
.objectType = OBJECT_DATABASE,
531+
.operationType = DIST_OPS_ALTER,
532+
.address = NULL,
533+
.markDistributed = false,
534+
};
525535

526536
static DistributeObjectOps Domain_Alter = {
527537
.deparse = DeparseAlterDomainStmt,
@@ -2087,6 +2097,11 @@ GetDistributeObjectOps(Node *node)
20872097
return &Collation_Rename;
20882098
}
20892099

2100+
case OBJECT_DATABASE:
2101+
{
2102+
return &Database_Rename;
2103+
}
2104+
20902105
case OBJECT_DOMAIN:
20912106
{
20922107
return &Domain_Rename;

src/backend/distributed/deparser/deparse_database_stmts.c

Lines changed: 77 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
static void AppendAlterDatabaseOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt);
3131
static void AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt);
3232
static void AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt);
33-
static void AppendDefElemConnLimit(StringInfo buf, DefElem *def);
3433
static void AppendCreateDatabaseStmt(StringInfo buf, CreatedbStmt *stmt);
3534
static void AppendDropDatabaseStmt(StringInfo buf, DropdbStmt *stmt);
3635
static void AppendGrantOnDatabaseStmt(StringInfo buf, GrantStmt *stmt);
36+
static void AppendBasicAlterDatabaseOptions(StringInfo buf, AlterDatabaseStmt *stmt);
37+
static void AppendGrantDatabases(StringInfo buf, GrantStmt *stmt);
38+
static void AppendAlterDatabaseSetTablespace(StringInfo buf, DefElem *def, char *dbname);
3739

38-
const DefElemOptionFormat create_database_option_formats[] = {
40+
const DefElemOptionFormat createDatabaseOptionFormats[] = {
3941
{ "owner", " OWNER %s", OPTION_FORMAT_STRING },
4042
{ "template", " TEMPLATE %s", OPTION_FORMAT_STRING },
4143
{ "encoding", " ENCODING %s", OPTION_FORMAT_LITERAL_CSTR },
@@ -53,6 +55,14 @@ const DefElemOptionFormat create_database_option_formats[] = {
5355
{ "is_template", " IS_TEMPLATE %s", OPTION_FORMAT_BOOLEAN }
5456
};
5557

58+
59+
const DefElemOptionFormat alterDatabaseOptionFormats[] = {
60+
{ "is_template", " IS_TEMPLATE %s", OPTION_FORMAT_BOOLEAN },
61+
{ "allow_connections", " ALLOW_CONNECTIONS %s", OPTION_FORMAT_BOOLEAN },
62+
{ "connection_limit", " CONNECTION LIMIT %d", OPTION_FORMAT_INTEGER },
63+
};
64+
65+
5666
char *
5767
DeparseAlterDatabaseOwnerStmt(Node *node)
5868
{
@@ -111,52 +121,67 @@ AppendGrantOnDatabaseStmt(StringInfo buf, GrantStmt *stmt)
111121
}
112122

113123

114-
static void
115-
AppendDefElemConnLimit(StringInfo buf, DefElem *def)
116-
{
117-
appendStringInfo(buf, " CONNECTION LIMIT %ld", (long int) defGetNumeric(def));
118-
}
119-
120-
121124
static void
122125
AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt)
123126
{
124-
appendStringInfo(buf, "ALTER DATABASE %s ", quote_identifier(stmt->dbname));
127+
if (list_length(stmt->options) == 0)
128+
{
129+
elog(ERROR, "got unexpected number of options for ALTER DATABASE");
130+
}
125131

126132
if (stmt->options)
127133
{
128-
ListCell *cell = NULL;
129-
appendStringInfo(buf, "WITH ");
130-
foreach(cell, stmt->options)
134+
DefElem *firstOption = linitial(stmt->options);
135+
if (strcmp(firstOption->defname, "tablespace") == 0)
131136
{
132-
DefElem *def = castNode(DefElem, lfirst(cell));
133-
if (strcmp(def->defname, "is_template") == 0)
134-
{
135-
appendStringInfo(buf, "IS_TEMPLATE %s",
136-
quote_literal_cstr(strVal(def->arg)));
137-
}
138-
else if (strcmp(def->defname, "connection_limit") == 0)
139-
{
140-
AppendDefElemConnLimit(buf, def);
141-
}
142-
else if (strcmp(def->defname, "allow_connections") == 0)
143-
{
144-
ereport(ERROR,
145-
errmsg("ALLOW_CONNECTIONS is not supported"));
146-
}
147-
else
148-
{
149-
ereport(ERROR,
150-
errmsg("unrecognized ALTER DATABASE option: %s",
151-
def->defname));
152-
}
137+
AppendAlterDatabaseSetTablespace(buf, firstOption, stmt->dbname);
138+
139+
/* SET tablespace cannot be combined with other options */
140+
return;
153141
}
142+
143+
144+
appendStringInfo(buf, "ALTER DATABASE %s WITH",
145+
quote_identifier(stmt->dbname));
146+
147+
AppendBasicAlterDatabaseOptions(buf, stmt);
154148
}
155149

156150
appendStringInfo(buf, ";");
157151
}
158152

159153

154+
static void
155+
AppendAlterDatabaseSetTablespace(StringInfo buf, DefElem *def, char *dbname)
156+
{
157+
appendStringInfo(buf,
158+
"ALTER DATABASE %s SET TABLESPACE %s",
159+
quote_identifier(dbname), quote_identifier(defGetString(def)));
160+
}
161+
162+
163+
/*
164+
* AppendBasicAlterDatabaseOptions appends basic ALTER DATABASE options to a string buffer.
165+
* Basic options are those that can be appended to the ALTER DATABASE statement
166+
* after the "WITH" keyword.(i.e. ALLOW_CONNECTIONS, CONNECTION LIMIT, IS_TEMPLATE)
167+
* For example, the tablespace option is not a basic option since it is defined via SET keyword.
168+
*
169+
* This function takes a string buffer and an AlterDatabaseStmt as input.
170+
* It appends the basic options to the string buffer.
171+
*
172+
*/
173+
static void
174+
AppendBasicAlterDatabaseOptions(StringInfo buf, AlterDatabaseStmt *stmt)
175+
{
176+
DefElem *def = NULL;
177+
foreach_ptr(def, stmt->options)
178+
{
179+
DefElemOptionToStatement(buf, def, alterDatabaseOptionFormats, lengthof(
180+
alterDatabaseOptionFormats));
181+
}
182+
}
183+
184+
160185
char *
161186
DeparseGrantOnDatabaseStmt(Node *node)
162187
{
@@ -216,6 +241,22 @@ AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt)
216241
}
217242

218243

244+
char *
245+
DeparseAlterDatabaseRenameStmt(Node *node)
246+
{
247+
RenameStmt *stmt = (RenameStmt *) node;
248+
249+
StringInfoData str;
250+
initStringInfo(&str);
251+
252+
appendStringInfo(&str, "ALTER DATABASE %s RENAME TO %s",
253+
quote_identifier(stmt->subname),
254+
quote_identifier(stmt->newname));
255+
256+
return str.data;
257+
}
258+
259+
219260
char *
220261
DeparseAlterDatabaseSetStmt(Node *node)
221262
{
@@ -246,8 +287,8 @@ AppendCreateDatabaseStmt(StringInfo buf, CreatedbStmt *stmt)
246287
DefElem *option = NULL;
247288
foreach_ptr(option, stmt->options)
248289
{
249-
DefElemOptionToStatement(buf, option, create_database_option_formats,
250-
lengthof(create_database_option_formats));
290+
DefElemOptionToStatement(buf, option, createDatabaseOptionFormats,
291+
lengthof(createDatabaseOptionFormats));
251292
}
252293
}
253294

src/include/distributed/commands.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ extern List * DropDatabaseStmtObjectAddress(Node *node, bool missingOk,
244244
bool isPostprocess);
245245
extern List * CreateDatabaseStmtObjectAddress(Node *node, bool missingOk,
246246
bool isPostprocess);
247+
extern List * GenerateGrantDatabaseCommandList(void);
248+
extern List * PostprocessAlterDatabaseRenameStmt(Node *node, const char *queryString);
247249
extern void EnsureSupportedCreateDatabaseCommand(CreatedbStmt *stmt);
248250
extern char * CreateDatabaseDDLCommand(Oid dbId);
249251

src/include/distributed/deparser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ extern char * DeparseAlterDatabaseRefreshCollStmt(Node *node);
251251
extern char * DeparseAlterDatabaseSetStmt(Node *node);
252252
extern char * DeparseCreateDatabaseStmt(Node *node);
253253
extern char * DeparseDropDatabaseStmt(Node *node);
254+
extern char * DeparseAlterDatabaseRenameStmt(Node *node);
254255

255256

256257
/* forward declaration for deparse_publication_stmts.c */

0 commit comments

Comments
 (0)