From 78991cab7ced571d9d62b6e74f60a45c679deef9 Mon Sep 17 00:00:00 2001 From: gindibay Date: Mon, 4 Sep 2023 10:45:17 +0300 Subject: [PATCH] Ads set statement --- .../commands/distribute_object_ops.c | 8 +- .../deparser/citus_deparse_set_utils.c | 165 ++++++++++++++++++ .../deparser/deparse_database_stmts.c | 141 ++++++++++++--- 3 files changed, 288 insertions(+), 26 deletions(-) create mode 100644 src/backend/distributed/deparser/citus_deparse_set_utils.c diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 6aa4b55f3..0f109465d 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -448,7 +448,7 @@ static DistributeObjectOps Database_Alter = { .deparse = DeparseAlterDatabaseStmt, .qualify = NULL, .preprocess = PreprocessAlterDatabaseStmt, - .postprocess = PostprocessAlterDistributedObjectStmt, + .postprocess = NULL, .objectType = OBJECT_DATABASE, .operationType = DIST_OPS_ALTER, .address = NULL, @@ -459,7 +459,7 @@ static DistributeObjectOps Database_Set = { .deparse = DeparseAlterDatabaseSetStmt, .qualify = NULL, .preprocess = PreprocessAlterDatabaseSetStmt, - .postprocess = PostprocessAlterDistributedObjectStmt, + .postprocess = NULL, .objectType = OBJECT_DATABASE, .operationType = DIST_OPS_ALTER, .address = NULL, @@ -468,7 +468,7 @@ static DistributeObjectOps Database_Set = { static DistributeObjectOps Database_Rename = { .deparse = DeparseAlterDatabaseRenameStmt, .qualify = NULL, - .preprocess = PreprocessAlterDatabaseRenameStmt, + .preprocess = NULL, .postprocess = NULL, .objectType = OBJECT_DATABASE, .operationType = DIST_OPS_ALTER, @@ -479,7 +479,7 @@ static DistributeObjectOps Database_Rename = { static DistributeObjectOps Database_RefreshColl = { .deparse = DeparseAlterDatabaseRefreshCollStmt, .qualify = NULL, - .preprocess = PreprocessAlterDatabaseRefreshCollStmt, + .preprocess = NULL,//TODO: Add PostprocessAfter adding addresses .postprocess = NULL, .objectType = OBJECT_DATABASE, .operationType = DIST_OPS_ALTER, diff --git a/src/backend/distributed/deparser/citus_deparse_set_utils.c b/src/backend/distributed/deparser/citus_deparse_set_utils.c new file mode 100644 index 000000000..7f9119c0f --- /dev/null +++ b/src/backend/distributed/deparser/citus_deparse_set_utils.c @@ -0,0 +1,165 @@ +#include "postgres.h" + +#include "lib/stringinfo.h" +#include "nodes/nodes.h" +#include "parser/parse_type.h" +#include "utils/builtins.h" +#include "utils/guc.h" + + +static void +AppendVarSetValue2(StringInfo buf, VariableSetStmt *setStmt); +static void +AppendVariableSet2(StringInfo buf, VariableSetStmt *setStmt); + + +static void +AppendVarSetValue2(StringInfo buf, VariableSetStmt *setStmt) +{ + ListCell *varArgCell = NULL; + ListCell *firstCell = list_head(setStmt->args); + + Assert(setStmt->kind == VAR_SET_VALUE); + + foreach(varArgCell, setStmt->args) + { + Node *varArgNode = lfirst(varArgCell); + A_Const *varArgConst = NULL; + TypeName *typeName = NULL; + + if (IsA(varArgNode, A_Const)) + { + varArgConst = (A_Const *) varArgNode; + } + else if (IsA(varArgNode, TypeCast)) + { + TypeCast *varArgTypeCast = (TypeCast *) varArgNode; + + varArgConst = castNode(A_Const, varArgTypeCast->arg); + typeName = varArgTypeCast->typeName; + } + else + { + elog(ERROR, "unrecognized node type: %d", varArgNode->type); + } + + /* don't know how to start SET until we inspect first arg */ + if (varArgCell != firstCell) + { + appendStringInfoChar(buf, ','); + } + else if (typeName != NULL) + { + appendStringInfoString(buf, " SET TIME ZONE"); + } + else + { + appendStringInfo(buf, " SET %s =", quote_identifier(setStmt->name)); + } + + Node *value = (Node *) &varArgConst->val; + switch (value->type) + { + case T_Integer: + { + appendStringInfo(buf, " %d", intVal(value)); + break; + } + + case T_Float: + { + appendStringInfo(buf, " %s", strVal(value)); + break; + } + + case T_String: + { + if (typeName != NULL) + { + /* + * Must be a ConstInterval argument for TIME ZONE. Coerce + * to interval and back to normalize the value and account + * for any typmod. + */ + Oid typoid = InvalidOid; + int32 typmod = -1; + + typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod); + Assert(typoid == INTERVALOID); + + Datum interval = + DirectFunctionCall3(interval_in, + CStringGetDatum(strVal(value)), + ObjectIdGetDatum(InvalidOid), + Int32GetDatum(typmod)); + + char *intervalout = + DatumGetCString(DirectFunctionCall1(interval_out, + interval)); + appendStringInfo(buf, " INTERVAL '%s'", intervalout); + } + else + { + appendStringInfo(buf, " %s", quote_literal_cstr(strVal( + value))); + } + break; + } + + default: + { + elog(ERROR, "Unexpected Value type in VAR_SET_VALUE arguments."); + break; + } + } + } +} + +/* + * AppendVariableSet appends a string representing the VariableSetStmt to a buffer + */ +static void +AppendVariableSet2(StringInfo buf, VariableSetStmt *setStmt) +{ + switch (setStmt->kind) + { + case VAR_SET_VALUE: + { + AppendVarSetValue2(buf, setStmt); + break; + } + + case VAR_SET_CURRENT: + { + appendStringInfo(buf, " SET %s FROM CURRENT", quote_identifier( + setStmt->name)); + break; + } + + case VAR_SET_DEFAULT: + { + appendStringInfo(buf, " SET %s TO DEFAULT", quote_identifier(setStmt->name)); + break; + } + + case VAR_RESET: + { + appendStringInfo(buf, " RESET %s", quote_identifier(setStmt->name)); + break; + } + + case VAR_RESET_ALL: + { + appendStringInfoString(buf, " RESET ALL"); + break; + } + + /* VAR_SET_MULTI is a special case for SET TRANSACTION that should not occur here */ + case VAR_SET_MULTI: + default: + { + ereport(ERROR, (errmsg("Unable to deparse SET statement"))); + break; + } + } +} diff --git a/src/backend/distributed/deparser/deparse_database_stmts.c b/src/backend/distributed/deparser/deparse_database_stmts.c index 09271896a..acfd328cc 100644 --- a/src/backend/distributed/deparser/deparse_database_stmts.c +++ b/src/backend/distributed/deparser/deparse_database_stmts.c @@ -20,6 +20,7 @@ #include "distributed/deparser.h" #include "distributed/citus_ruleutils.h" +#include "commands/defrem.h" #include "distributed/deparser.h" #include "distributed/log_utils.h" @@ -31,7 +32,7 @@ char * DeparseAlterDatabaseOwnerStmt(Node *node) { AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node); - StringInfoData str = { 0 }; + StringInfoData str = {0}; initStringInfo(&str); Assert(stmt->objectType == OBJECT_DATABASE); @@ -41,7 +42,6 @@ DeparseAlterDatabaseOwnerStmt(Node *node) return str.data; } - static void AppendAlterDatabaseOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt) { @@ -49,18 +49,17 @@ AppendAlterDatabaseOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt) appendStringInfo(buf, "ALTER DATABASE %s OWNER TO %s;", - quote_identifier(strVal((String *) stmt->object)), + 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) + foreach (cell, stmt->objects) { char *database = strVal(lfirst(cell)); appendStringInfoString(buf, quote_identifier(database)); @@ -71,7 +70,6 @@ AppendGrantDatabases(StringInfo buf, GrantStmt *stmt) } } - static void AppendGrantOnDatabaseStmt(StringInfo buf, GrantStmt *stmt) { @@ -141,6 +139,11 @@ AppendAlterDatabaseSetStmt(StringInfo buf, AlterDatabaseSetStmt *stmt) 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) @@ -150,12 +153,112 @@ AppendAlterDatabaseStmt(StringInfo buf, AlterDatabaseStmt *stmt) if (stmt->options) { ListCell *cell = NULL; - appendStringInfo(buf, "WITH OPTION "); + appendStringInfo(buf, "WITH "); foreach(cell, stmt->options) { DefElem *def = castNode(DefElem, lfirst(cell)); - appendStringInfo(buf, "%s %s", quote_identifier(def->defname), - quote_literal_cstr(strVal(def->arg))); + 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, ", "); @@ -205,7 +308,7 @@ DeparseGrantOnDatabaseStmt(Node *node) GrantStmt *stmt = castNode(GrantStmt, node); Assert(stmt->objtype == OBJECT_DATABASE); - StringInfoData str = { 0 }; + StringInfoData str = {0}; initStringInfo(&str); AppendGrantOnDatabaseStmt(&str, stmt); @@ -213,13 +316,12 @@ DeparseGrantOnDatabaseStmt(Node *node) return str.data; } - char * DeparseAlterDatabaseStmt(Node *node) { AlterDatabaseStmt *stmt = castNode(AlterDatabaseStmt, node); - StringInfoData str = { 0 }; + StringInfoData str = {0}; initStringInfo(&str); AppendAlterDatabaseStmt(&str, stmt); @@ -227,13 +329,12 @@ DeparseAlterDatabaseStmt(Node *node) return str.data; } - char * DeparseAlterDatabaseSetStmt(Node *node) { AlterDatabaseSetStmt *stmt = castNode(AlterDatabaseSetStmt, node); - StringInfoData str = { 0 }; + StringInfoData str = {0}; initStringInfo(&str); AppendAlterDatabaseSetStmt(&str, stmt); @@ -241,32 +342,28 @@ DeparseAlterDatabaseSetStmt(Node *node) return str.data; } - char * DeparseAlterDatabaseRenameStmt(Node *node) { - RenameStmt *stmt = (RenameStmt *) 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)); + 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; + AlterDatabaseRefreshCollStmt *stmt = (AlterDatabaseRefreshCollStmt *)node; StringInfoData str; initStringInfo(&str); - appendStringInfo(&str, "ALTER DATABASE %s REFRESH COLLATION;", quote_identifier( - stmt->dbname)); + appendStringInfo(&str, "ALTER DATABASE %s REFRESH COLLATION;", quote_identifier(stmt->dbname)); return str.data; }