/*------------------------------------------------------------------------- * * deparse_database_stmts.c * * All routines to deparse database statements. * * Copyright (c), Citus Data, Inc. * *------------------------------------------------------------------------- */ #include "postgres.h" #include "pg_version_compat.h" #include "catalog/namespace.h" #include "lib/stringinfo.h" #include "nodes/parsenodes.h" #include "utils/builtins.h" #include "distributed/deparser.h" #include "distributed/citus_ruleutils.h" #include "commands/defrem.h" #include "distributed/deparser.h" #include "distributed/log_utils.h" static void AppendAlterDatabaseOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt); static void AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt); static void AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt); char * DeparseAlterDatabaseOwnerStmt(Node *node) { AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node); StringInfoData str = {0}; initStringInfo(&str); Assert(stmt->objectType == OBJECT_DATABASE); AppendAlterDatabaseOwnerStmt(&str, stmt); return str.data; } static void AppendAlterDatabaseOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt) { Assert(stmt->objectType == OBJECT_DATABASE); appendStringInfo(buf, "ALTER DATABASE %s OWNER TO %s;", quote_identifier(strVal((String *)stmt->object)), RoleSpecString(stmt->newowner, true)); } static void AppendGrantDatabases(StringInfo buf, GrantStmt *stmt) { ListCell *cell = NULL; appendStringInfo(buf, " ON DATABASE "); foreach (cell, stmt->objects) { char *database = strVal(lfirst(cell)); appendStringInfoString(buf, quote_identifier(database)); if (cell != list_tail(stmt->objects)) { appendStringInfo(buf, ", "); } } } static void AppendGrantOnDatabaseStmt(StringInfo buf, GrantStmt *stmt) { Assert(stmt->objtype == OBJECT_DATABASE); AppendGrantSharedPrefix(buf, stmt); AppendGrantDatabases(buf, stmt); AppendGrantSharedSuffix(buf, stmt); } static void AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt) { appendStringInfo(buf, "ALTER DATABASE %s ", quote_identifier(stmt->dbname)); if (stmt->options) { ListCell *cell = NULL; appendStringInfo(buf, "WITH OPTION "); foreach(cell, stmt->options) { DefElem *def = castNode(DefElem, lfirst(cell)); appendStringInfo(buf, "%s %s", quote_identifier(def->defname), quote_literal_cstr(strVal(def->arg))); if (cell != list_tail(stmt->options)) { appendStringInfo(buf, ", "); } } } appendStringInfo(buf, ";"); } static void AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt) { appendStringInfo(buf, "ALTER DATABASE %s SET ", quote_identifier(stmt->dbname)); VariableSetStmt *varSetStmt = castNode(VariableSetStmt, stmt->setstmt); if (varSetStmt->kind == VAR_SET_VALUE) { appendStringInfo(buf, "%s = %s", quote_identifier(varSetStmt->name), quote_literal_cstr(strVal(varSetStmt->args))); } else if (varSetStmt->kind == VAR_RESET_ALL) { appendStringInfo(buf, "RESET ALL"); } else if (varSetStmt->kind == VAR_RESET) { appendStringInfo(buf, "RESET %s", quote_identifier(varSetStmt->name)); } else { ereport(ERROR, errmsg("unrecognized AlterDatabaseSetStmt kind: %d", varSetStmt->kind)); } appendStringInfo(buf, ";"); } static void AppendDefElemConnLimit(StringInfo buf, DefElem *def) { appendStringInfo(buf, " CONNECTION LIMIT %ld",(long int) defGetNumeric(def)); } static void AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt) { appendStringInfo(buf, "ALTER DATABASE %s ", quote_identifier(stmt->dbname)); if (stmt->options) { ListCell *cell = NULL; appendStringInfo(buf, "WITH "); foreach(cell, stmt->options) { DefElem *def = castNode(DefElem, lfirst(cell)); printf("test"); if (strcmp(def->defname, "is_template") == 0) { appendStringInfo(buf, "%s %s", quote_identifier(def->defname), quote_literal_cstr(strVal(def->arg))); } else if (strcmp(def->defname, "connection_limit") == 0) { AppendDefElemConnLimit(buf, def); } else if (strcmp(def->defname, "allow_connections") == 0) { ereport(ERROR, errmsg("ALLOW_CONNECTIONS is not supported")); } else{ ereport(ERROR, errmsg("unrecognized AlterDatabaseStmt option: %s", def->defname)); } if (cell != list_tail(stmt->options)) { appendStringInfo(buf, ", "); } } } appendStringInfo(buf, ";"); } static void AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt) { appendStringInfo(buf, "ALTER DATABASE %s SET ", quote_identifier(stmt->dbname)); VariableSetStmt *varSetStmt = castNode(VariableSetStmt, stmt->setstmt); if (varSetStmt->kind == VAR_SET_VALUE) { appendStringInfo(buf, "%s = %s", quote_identifier(varSetStmt->name), quote_literal_cstr(strVal(varSetStmt->args))); } else if (varSetStmt->kind == VAR_RESET_ALL) { appendStringInfo(buf, "RESET ALL"); } else if (varSetStmt->kind == VAR_RESET) { appendStringInfo(buf, "RESET %s", quote_identifier(varSetStmt->name)); } else { ereport(ERROR, errmsg("unrecognized AlterDatabaseSetStmt kind: %d", varSetStmt->kind)); } appendStringInfo(buf, ";"); } static void AppendDefElemConnLimit(StringInfo buf, DefElem *def) { appendStringInfo(buf, " CONNECTION LIMIT %ld",(long int) defGetNumeric(def)); } static void AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt) { appendStringInfo(buf, "ALTER DATABASE %s ", quote_identifier(stmt->dbname)); if (stmt->options) { ListCell *cell = NULL; appendStringInfo(buf, "WITH "); foreach(cell, stmt->options) { DefElem *def = castNode(DefElem, lfirst(cell)); printf("test"); if (strcmp(def->defname, "is_template") == 0) { appendStringInfo(buf, "%s %s", quote_identifier(def->defname), quote_literal_cstr(strVal(def->arg))); } else if (strcmp(def->defname, "connection_limit") == 0) { AppendDefElemConnLimit(buf, def); } else if (strcmp(def->defname, "allow_connections") == 0) { ereport(ERROR, errmsg("ALLOW_CONNECTIONS is not supported")); } else{ ereport(ERROR, errmsg("unrecognized AlterDatabaseStmt option: %s", def->defname)); } if (cell != list_tail(stmt->options)) { appendStringInfo(buf, ", "); } } } appendStringInfo(buf, ";"); } static void AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt) { appendStringInfo(buf, "ALTER DATABASE %s SET ", quote_identifier(stmt->dbname)); VariableSetStmt *varSetStmt = castNode(VariableSetStmt, stmt->setstmt); if (varSetStmt->kind == VAR_SET_VALUE) { appendStringInfo(buf, "%s = %s", quote_identifier(varSetStmt->name), quote_literal_cstr(strVal(varSetStmt->args))); } else if (varSetStmt->kind == VAR_RESET_ALL) { appendStringInfo(buf, "RESET ALL"); } else if (varSetStmt->kind == VAR_RESET) { appendStringInfo(buf, "RESET %s", quote_identifier(varSetStmt->name)); } else { ereport(ERROR, errmsg("unrecognized AlterDatabaseSetStmt kind: %d", varSetStmt->kind)); } appendStringInfo(buf, ";"); } char * DeparseGrantOnDatabaseStmt(Node *node) { GrantStmt *stmt = castNode(GrantStmt, node); Assert(stmt->objtype == OBJECT_DATABASE); StringInfoData str = {0}; initStringInfo(&str); AppendGrantOnDatabaseStmt(&str, stmt); return str.data; } char * DeparseAlterDatabaseStmt(Node *node) { AlterDatabaseStmt *stmt = castNode(AlterDatabaseStmt, node); StringInfoData str = {0}; initStringInfo(&str); AppendAlterDatabaseStmt(&str, stmt); return str.data; } char * DeparseAlterDatabaseSetStmt(Node *node) { AlterDatabaseSetStmt *stmt = castNode(AlterDatabaseSetStmt, node); StringInfoData str = {0}; initStringInfo(&str); AppendAlterDatabaseSetStmt(&str, stmt); return str.data; } char * DeparseAlterDatabaseRenameStmt(Node *node) { RenameStmt *stmt = (RenameStmt *)node; StringInfoData str; initStringInfo(&str); appendStringInfo(&str, "ALTER DATABASE %s RENAME TO %s;", quote_identifier(stmt->subname), quote_identifier(stmt->newname)); return str.data; } char * DeparseAlterDatabaseRefreshCollStmt(Node *node) { AlterDatabaseRefreshCollStmt *stmt = (AlterDatabaseRefreshCollStmt *)node; StringInfoData str; initStringInfo(&str); appendStringInfo(&str, "ALTER DATABASE %s REFRESH COLLATION;", quote_identifier(stmt->dbname)); return str.data; }