citus/src/backend/distributed/deparser/deparse_foreign_server_stmts.c

278 lines
5.8 KiB
C

/*-------------------------------------------------------------------------
*
* deparse_foreign_server_stmts.c
* All routines to deparse foreign server statements.
*
* Copyright (c) Citus Data, Inc.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "commands/defrem.h"
#include "distributed/citus_ruleutils.h"
#include "distributed/deparser.h"
#include "distributed/listutils.h"
#include "distributed/relay_utility.h"
#include "lib/stringinfo.h"
#include "nodes/nodes.h"
#include "utils/builtins.h"
static void AppendCreateForeignServerStmt(StringInfo buf, CreateForeignServerStmt *stmt);
static void AppendAlterForeignServerStmt(StringInfo buf, AlterForeignServerStmt *stmt);
static void AppendAlterForeignServerOptions(StringInfo buf, AlterForeignServerStmt *stmt);
static void AppendAlterForeignServerRenameStmt(StringInfo buf, RenameStmt *stmt);
static void AppendAlterForeignServerOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt);
static void AppendDropForeignServerStmt(StringInfo buf, DropStmt *stmt);
static void AppendServerNames(StringInfo buf, DropStmt *stmt);
static void AppendBehavior(StringInfo buf, DropStmt *stmt);
static char * GetDefElemActionString(DefElemAction action);
char *
DeparseCreateForeignServerStmt(Node *node)
{
CreateForeignServerStmt *stmt = castNode(CreateForeignServerStmt, node);
StringInfoData str;
initStringInfo(&str);
AppendCreateForeignServerStmt(&str, stmt);
return str.data;
}
char *
DeparseAlterForeignServerStmt(Node *node)
{
AlterForeignServerStmt *stmt = castNode(AlterForeignServerStmt, node);
StringInfoData str;
initStringInfo(&str);
AppendAlterForeignServerStmt(&str, stmt);
return str.data;
}
char *
DeparseAlterForeignServerRenameStmt(Node *node)
{
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_FOREIGN_SERVER);
StringInfoData str;
initStringInfo(&str);
AppendAlterForeignServerRenameStmt(&str, stmt);
return str.data;
}
char *
DeparseAlterForeignServerOwnerStmt(Node *node)
{
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_FOREIGN_SERVER);
StringInfoData str;
initStringInfo(&str);
AppendAlterForeignServerOwnerStmt(&str, stmt);
return str.data;
}
char *
DeparseDropForeignServerStmt(Node *node)
{
DropStmt *stmt = castNode(DropStmt, node);
Assert(stmt->removeType == OBJECT_FOREIGN_SERVER);
StringInfoData str;
initStringInfo(&str);
AppendDropForeignServerStmt(&str, stmt);
return str.data;
}
static void
AppendCreateForeignServerStmt(StringInfo buf, CreateForeignServerStmt *stmt)
{
appendStringInfoString(buf, "CREATE SERVER ");
if (stmt->if_not_exists)
{
appendStringInfoString(buf, "IF NOT EXISTS ");
}
appendStringInfo(buf, "%s ", quote_identifier(stmt->servername));
if (stmt->servertype)
{
appendStringInfo(buf, "TYPE %s ", quote_literal_cstr(stmt->servertype));
}
if (stmt->version)
{
appendStringInfo(buf, "VERSION %s ", quote_literal_cstr(stmt->version));
}
appendStringInfo(buf, "FOREIGN DATA WRAPPER %s ", quote_identifier(stmt->fdwname));
AppendOptionListToString(buf, stmt->options);
}
static void
AppendAlterForeignServerStmt(StringInfo buf, AlterForeignServerStmt *stmt)
{
appendStringInfo(buf, "ALTER SERVER %s ", quote_identifier(stmt->servername));
if (stmt->has_version)
{
appendStringInfo(buf, "VERSION %s ", quote_literal_cstr(stmt->version));
}
AppendAlterForeignServerOptions(buf, stmt);
}
static void
AppendAlterForeignServerOptions(StringInfo buf, AlterForeignServerStmt *stmt)
{
if (list_length(stmt->options) <= 0)
{
return;
}
appendStringInfoString(buf, "OPTIONS (");
DefElemAction action = DEFELEM_UNSPEC;
DefElem *def = NULL;
foreach_ptr(def, stmt->options)
{
if (def->defaction != DEFELEM_UNSPEC)
{
action = def->defaction;
char *actionString = GetDefElemActionString(action);
appendStringInfo(buf, "%s ", actionString);
}
appendStringInfo(buf, "%s", quote_identifier(def->defname));
if (action != DEFELEM_DROP)
{
const char *value = quote_literal_cstr(defGetString(def));
appendStringInfo(buf, " %s", value);
}
if (def != llast(stmt->options))
{
appendStringInfoString(buf, ", ");
}
}
appendStringInfoString(buf, ")");
}
static void
AppendAlterForeignServerRenameStmt(StringInfo buf, RenameStmt *stmt)
{
appendStringInfo(buf, "ALTER SERVER %s RENAME TO %s",
quote_identifier(strVal(stmt->object)),
quote_identifier(stmt->newname));
}
static void
AppendAlterForeignServerOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt)
{
const char *servername = quote_identifier(strVal(stmt->object));
appendStringInfo(buf, "ALTER SERVER %s OWNER TO ", servername);
appendStringInfo(buf, "%s", RoleSpecString(stmt->newowner, true));
}
static void
AppendDropForeignServerStmt(StringInfo buf, DropStmt *stmt)
{
appendStringInfoString(buf, "DROP SERVER ");
if (stmt->missing_ok)
{
appendStringInfoString(buf, "IF EXISTS ");
}
AppendServerNames(buf, stmt);
AppendBehavior(buf, stmt);
}
static void
AppendServerNames(StringInfo buf, DropStmt *stmt)
{
Value *serverValue = NULL;
foreach_ptr(serverValue, stmt->objects)
{
const char *serverString = quote_identifier(strVal(serverValue));
appendStringInfo(buf, "%s", serverString);
if (serverValue != llast(stmt->objects))
{
appendStringInfoString(buf, ", ");
}
}
}
static void
AppendBehavior(StringInfo buf, DropStmt *stmt)
{
if (stmt->behavior == DROP_CASCADE)
{
appendStringInfoString(buf, " CASCADE");
}
else if (stmt->behavior == DROP_RESTRICT)
{
appendStringInfoString(buf, " RESTRICT");
}
}
static char *
GetDefElemActionString(DefElemAction action)
{
switch (action)
{
case DEFELEM_ADD:
{
return "ADD";
}
case DEFELEM_SET:
{
return "SET";
}
case DEFELEM_DROP:
{
return "DROP";
}
default:
return "";
}
}