#include "postgres.h"
#include "catalog/index.h"
#include "catalog/pg_am.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_class.h"
#include "catalog/pg_trigger.h"
#include "commands/trigger.h"
#include "common/keywords.h"
#include "common/kwlookup.h"
#include "lib/stringinfo.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/timestamp.h"
#include "utils/xml.h"
typedef enum DeparseNodeContext {
DEPARSE_NODE_CONTEXT_NONE,
DEPARSE_NODE_CONTEXT_INSERT_RELATION,
DEPARSE_NODE_CONTEXT_A_EXPR,
DEPARSE_NODE_CONTEXT_CREATE_TYPE,
DEPARSE_NODE_CONTEXT_ALTER_TYPE,
DEPARSE_NODE_CONTEXT_SET_STATEMENT,
DEPARSE_NODE_CONTEXT_FUNC_EXPR,
DEPARSE_NODE_CONTEXT_IDENTIFIER,
DEPARSE_NODE_CONTEXT_CONSTANT
} DeparseNodeContext;
static void
removeTrailingSpace(StringInfo str)
{
if (str->len >= 1 && str->data[str->len - 1] == ' ') {
str->len -= 1;
str->data[str->len] = '\0';
}
}
static void
deparseStringLiteral(StringInfo buf, const char *val)
{
const char *valptr;
if (strchr(val, '\\') != NULL)
appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
appendStringInfoChar(buf, '\'');
for (valptr = val; *valptr; valptr++)
{
char ch = *valptr;
if (SQL_STR_DOUBLE(ch, true))
appendStringInfoChar(buf, ch);
appendStringInfoChar(buf, ch);
}
appendStringInfoChar(buf, '\'');
}
static bool
isReservedKeyword(const char *val)
{
int kwnum = ScanKeywordLookup(val, &ScanKeywords);
bool all_lower_case = true;
const char *cp;
for (cp = val; *cp; cp++)
{
if (!(
(*cp >= 'a' && *cp <= 'z') ||
(*cp >= '0' && *cp <= '9') ||
(*cp == '_')))
{
all_lower_case = false;
break;
}
}
return all_lower_case && kwnum >= 0 && ScanKeywordCategories[kwnum] == RESERVED_KEYWORD;
}
static bool
isOp(const char *val)
{
const char *cp;
Assert(strlen(val) > 0);
for (cp = val; *cp; cp++)
{
if (!(
*cp == '~' ||
*cp == '!' ||
*cp == '@' ||
*cp == '#' ||
*cp == '^' ||
*cp == '&' ||
*cp == '|' ||
*cp == '`' ||
*cp == '?' ||
*cp == '+' ||
*cp == '-' ||
*cp == '*' ||
*cp == '/' ||
*cp == '%' ||
*cp == '<' ||
*cp == '>' ||
*cp == '='))
return false;
}
return true;
}
static void deparseSelectStmt(StringInfo str, SelectStmt *stmt);
static void deparseIntoClause(StringInfo str, IntoClause *into_clause);
static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context);
static void deparseResTarget(StringInfo str, ResTarget *res_target, DeparseNodeContext context);
void deparseRawStmt(StringInfo str, RawStmt *raw_stmt);
static void deparseAlias(StringInfo str, Alias *alias);
static void deparseWindowDef(StringInfo str, WindowDef* window_def);
static void deparseColumnRef(StringInfo str, ColumnRef* column_ref);
static void deparseSubLink(StringInfo str, SubLink* sub_link);
static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context);
static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr);
static void deparseAStar(StringInfo str, A_Star* a_star);
static void deparseCollateClause(StringInfo str, CollateClause* collate_clause);
static void deparseSortBy(StringInfo str, SortBy* sort_by);
static void deparseParamRef(StringInfo str, ParamRef* param_ref);
static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function);
static void deparseWithClause(StringInfo str, WithClause *with_clause);
static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr);
static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte);
static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect);
static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context);
static void deparseTypeName(StringInfo str, TypeName *type_name);
static void deparseIntervalTypmods(StringInfo str, TypeName *type_name);
static void deparseNullTest(StringInfo str, NullTest *null_test);
static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection);
static void deparseAIndices(StringInfo str, A_Indices *a_indices);
static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr);
static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test);
static void deparseColumnDef(StringInfo str, ColumnDef *column_def);
static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt);
static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause);
static void deparseIndexElem(StringInfo str, IndexElem* index_elem);
static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt);
static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt);
static void deparseLockingClause(StringInfo str, LockingClause *locking_clause);
static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default);
static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt);
static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt);
static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter);
static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec);
static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt);
static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt);
static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt);
static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample);
static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func);
static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set);
static void deparseFuncCall(StringInfo str, FuncCall *func_call, DeparseNodeContext context);
static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr, DeparseNodeContext context);
static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
static void deparseJsonIsPredicate(StringInfo str, JsonIsPredicate *json_is_predicate);
static void deparseJsonObjectAgg(StringInfo str, JsonObjectAgg *json_object_agg);
static void deparseJsonArrayAgg(StringInfo str, JsonArrayAgg *json_array_agg);
static void deparseJsonObjectConstructor(StringInfo str, JsonObjectConstructor *json_object_constructor);
static void deparseJsonArrayConstructor(StringInfo str, JsonArrayConstructor *json_array_constructor);
static void deparseJsonArrayQueryConstructor(StringInfo str, JsonArrayQueryConstructor *json_array_query_constructor);
static void deparseJsonValueExpr(StringInfo str, JsonValueExpr *json_value_expr);
static void deparseJsonOutput(StringInfo str, JsonOutput *json_output);
static void deparseJsonParseExpr(StringInfo str, JsonParseExpr *json_parse_expr);
static void deparseJsonScalarExpr(StringInfo str, JsonScalarExpr *json_scalar_expr);
static void deparseJsonSerializeExpr(StringInfo str, JsonSerializeExpr *json_serialize_expr);
static void deparseJsonTable(StringInfo str, JsonTable *json_table);
static void deparseJsonTableColumn(StringInfo str, JsonTableColumn *json_table_column);
static void deparseJsonTableColumns(StringInfo str, List *json_table_columns);
static void deparseJsonTablePathSpec(StringInfo str, JsonTablePathSpec *json_table_path_spec);
static void deparseJsonBehavior(StringInfo str, JsonBehavior *json_behavior);
static void deparseJsonFuncExpr(StringInfo str, JsonFuncExpr *json_func_expr);
static void deparseJsonQuotesClauseOpt(StringInfo str, JsonQuotes quotes);
static void deparseJsonOnErrorClauseOpt(StringInfo str, JsonBehavior *behavior);
static void deparseJsonOnEmptyClauseOpt(StringInfo str, JsonBehavior *behavior);
static void deparseConstraint(StringInfo str, Constraint *constraint);
static void deparseSchemaStmt(StringInfo str, Node *node);
static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt);
static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition);
static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item);
static void deparseAConst(StringInfo str, A_Const *a_const);
static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func);
static void deparsePreparableStmt(StringInfo str, Node *node);
static void deparseRuleActionStmt(StringInfo str, Node *node);
static void deparseExplainableStmt(StringInfo str, Node *node);
static void deparseStmt(StringInfo str, Node *node);
static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context);
static void deparseAnyName(StringInfo str, List *parts)
{
ListCell *lc = NULL;
foreach(lc, parts)
{
Assert(IsA(lfirst(lc), String));
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
if (lnext(parts, lc))
appendStringInfoChar(str, '.');
}
}
static void deparseAnyNameSkipFirst(StringInfo str, List *parts)
{
ListCell *lc = NULL;
for_each_from(lc, parts, 1)
{
Assert(IsA(lfirst(lc), String));
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
if (lnext(parts, lc))
appendStringInfoChar(str, '.');
}
}
static void deparseAnyNameSkipLast(StringInfo str, List *parts)
{
ListCell *lc = NULL;
foreach (lc, parts)
{
if (lnext(parts, lc))
{
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
if (foreach_current_index(lc) < list_length(parts) - 2)
appendStringInfoChar(str, '.');
}
}
}
static void deparseFuncExpr(StringInfo str, Node *node, DeparseNodeContext context)
{
switch (nodeTag(node))
{
case T_FuncCall:
deparseFuncCall(str, castNode(FuncCall, node), context);
break;
case T_SQLValueFunction:
deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
break;
case T_MinMaxExpr:
deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
break;
case T_CoalesceExpr:
deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
break;
case T_XmlExpr:
deparseXmlExpr(str, castNode(XmlExpr, node), context);
break;
case T_XmlSerialize:
deparseXmlSerialize(str, castNode(XmlSerialize, node));
break;
case T_JsonObjectAgg:
deparseJsonObjectAgg(str, castNode(JsonObjectAgg, node));
break;
case T_JsonArrayAgg:
deparseJsonArrayAgg(str, castNode(JsonArrayAgg, node));
break;
case T_JsonObjectConstructor:
deparseJsonObjectConstructor(str, castNode(JsonObjectConstructor, node));
break;
case T_JsonArrayConstructor:
deparseJsonArrayConstructor(str, castNode(JsonArrayConstructor, node));
break;
case T_JsonArrayQueryConstructor:
deparseJsonArrayQueryConstructor(str, castNode(JsonArrayQueryConstructor, node));
break;
default:
elog(ERROR, "deparse: unpermitted node type in func_expr: %d",
(int) nodeTag(node));
break;
}
}
static void deparseCExpr(StringInfo str, Node *node);
static void deparseExpr(StringInfo str, Node *node, DeparseNodeContext context)
{
if (node == NULL)
return;
switch (nodeTag(node))
{
case T_ColumnRef:
case T_A_Const:
case T_ParamRef:
case T_A_Indirection:
case T_CaseExpr:
case T_SubLink:
case T_A_ArrayExpr:
case T_RowExpr:
case T_GroupingFunc:
deparseCExpr(str, node);
break;
case T_TypeCast:
deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
break;
case T_CollateClause:
deparseCollateClause(str, castNode(CollateClause, node));
break;
case T_A_Expr:
deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_A_EXPR);
break;
case T_BoolExpr:
deparseBoolExpr(str, castNode(BoolExpr, node));
break;
case T_NullTest:
deparseNullTest(str, castNode(NullTest, node));
break;
case T_BooleanTest:
deparseBooleanTest(str, castNode(BooleanTest, node));
break;
case T_JsonIsPredicate:
deparseJsonIsPredicate(str, castNode(JsonIsPredicate, node));
break;
case T_SetToDefault:
deparseSetToDefault(str, castNode(SetToDefault, node));
break;
case T_MergeSupportFunc:
appendStringInfoString(str, "merge_action() ");
break;
case T_JsonParseExpr:
deparseJsonParseExpr(str, castNode(JsonParseExpr, node));
break;
case T_JsonScalarExpr:
deparseJsonScalarExpr(str, castNode(JsonScalarExpr, node));
break;
case T_JsonSerializeExpr:
deparseJsonSerializeExpr(str, castNode(JsonSerializeExpr, node));
break;
case T_JsonFuncExpr:
deparseJsonFuncExpr(str, castNode(JsonFuncExpr, node));
break;
case T_FuncCall:
case T_SQLValueFunction:
case T_MinMaxExpr:
case T_CoalesceExpr:
case T_XmlExpr:
case T_XmlSerialize:
case T_JsonObjectAgg:
case T_JsonArrayAgg:
case T_JsonObjectConstructor:
case T_JsonArrayConstructor:
case T_JsonArrayQueryConstructor:
deparseFuncExpr(str, node, context);
break;
default:
elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr/c_expr: %d",
(int) nodeTag(node));
break;
}
}
static void deparseBExpr(StringInfo str, Node *node)
{
if (IsA(node, XmlExpr)) {
deparseXmlExpr(str, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE);
return;
}
if (IsA(node, A_Expr)) {
A_Expr *a_expr = castNode(A_Expr, node);
if (a_expr->kind == AEXPR_OP || a_expr->kind == AEXPR_DISTINCT || a_expr->kind == AEXPR_NOT_DISTINCT) {
deparseAExpr(str, a_expr, DEPARSE_NODE_CONTEXT_NONE);
return;
}
}
if (IsA(node, BoolExpr)) {
BoolExpr *bool_expr = castNode(BoolExpr, node);
if (bool_expr->boolop == NOT_EXPR) {
deparseBoolExpr(str, bool_expr);
return;
}
}
deparseCExpr(str, node);
}
static void deparseAexprConst(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_A_Const:
deparseAConst(str, castNode(A_Const, node));
break;
case T_TypeCast:
deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
break;
default:
elog(ERROR, "deparse: unpermitted node type in AexprConst: %d",
(int) nodeTag(node));
break;
}
}
static void deparseCExpr(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_ColumnRef:
deparseColumnRef(str, castNode(ColumnRef, node));
break;
case T_A_Const:
deparseAConst(str, castNode(A_Const, node));
break;
case T_ParamRef:
deparseParamRef(str, castNode(ParamRef, node));
break;
case T_A_Indirection:
deparseAIndirection(str, castNode(A_Indirection, node));
break;
case T_CaseExpr:
deparseCaseExpr(str, castNode(CaseExpr, node));
break;
case T_SubLink:
deparseSubLink(str, castNode(SubLink, node));
break;
case T_A_ArrayExpr:
deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
break;
case T_RowExpr:
deparseRowExpr(str, castNode(RowExpr, node));
break;
case T_GroupingFunc:
deparseGroupingFunc(str, castNode(GroupingFunc, node));
break;
case T_FuncCall:
case T_SQLValueFunction:
case T_MinMaxExpr:
case T_CoalesceExpr:
case T_XmlExpr:
case T_XmlSerialize:
case T_JsonObjectAgg:
case T_JsonArrayAgg:
case T_JsonObjectConstructor:
case T_JsonArrayConstructor:
case T_JsonArrayQueryConstructor:
deparseFuncExpr(str, node, DEPARSE_NODE_CONTEXT_NONE);
break;
default:
appendStringInfoChar(str, '(');
deparseExpr(str, node, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
break;
}
}
static void deparseExprList(StringInfo str, List *exprs)
{
ListCell *lc;
foreach(lc, exprs)
{
deparseExpr(str, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
if (lnext(exprs, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseColId(StringInfo str, char *s)
{
appendStringInfoString(str, quote_identifier(s));
}
static void deparseColLabel(StringInfo str, char *s)
{
appendStringInfoString(str, quote_identifier(s));
}
static void deparseSignedIconst(StringInfo str, Node *node)
{
appendStringInfo(str, "%d", intVal(node));
}
static void deparseOptIndirection(StringInfo str, List *indirection, int N)
{
ListCell *lc = NULL;
for_each_from(lc, indirection, N)
{
if (IsA(lfirst(lc), String))
{
appendStringInfoChar(str, '.');
deparseColLabel(str, strVal(lfirst(lc)));
}
else if (IsA(lfirst(lc), A_Star))
{
appendStringInfoString(str, ".*");
}
else if (IsA(lfirst(lc), A_Indices))
{
deparseAIndices(str, castNode(A_Indices, lfirst(lc)));
}
else
{
Assert(false);
}
}
}
static void deparseRoleList(StringInfo str, List *roles)
{
ListCell *lc;
foreach(lc, roles)
{
RoleSpec *role_spec = castNode(RoleSpec, lfirst(lc));
deparseRoleSpec(str, role_spec);
if (lnext(roles, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseSimpleTypename(StringInfo str, Node *node)
{
deparseTypeName(str, castNode(TypeName, node));
}
static void deparseNumericOnly(StringInfo str, union ValUnion *value)
{
switch (nodeTag(value))
{
case T_Integer:
appendStringInfo(str, "%d", value->ival.ival);
break;
case T_Float:
appendStringInfoString(str, value->sval.sval);
break;
default:
Assert(false);
}
}
static void deparseNumericOnlyList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseNumericOnly(str, (union ValUnion *) lfirst(lc));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
{
ListCell *lc;
if (strcmp(def_elem->defname, "as") == 0)
{
appendStringInfoString(str, "AS ");
deparseSimpleTypename(str, def_elem->arg);
}
else if (strcmp(def_elem->defname, "cache") == 0)
{
appendStringInfoString(str, "CACHE ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "cycle") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "CYCLE");
}
else if (strcmp(def_elem->defname, "cycle") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NO CYCLE");
}
else if (strcmp(def_elem->defname, "increment") == 0)
{
appendStringInfoString(str, "INCREMENT ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "MAXVALUE ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
{
appendStringInfoString(str, "NO MAXVALUE");
}
else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "MINVALUE ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
{
appendStringInfoString(str, "NO MINVALUE");
}
else if (strcmp(def_elem->defname, "owned_by") == 0)
{
appendStringInfoString(str, "OWNED BY ");
deparseAnyName(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "sequence_name") == 0)
{
appendStringInfoString(str, "SEQUENCE NAME ");
deparseAnyName(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "start") == 0)
{
appendStringInfoString(str, "START ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
{
appendStringInfoString(str, "RESTART");
}
else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "RESTART ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else
{
Assert(false);
}
}
static void deparseSeqOptList(StringInfo str, List *options)
{
ListCell *lc;
Assert(list_length(options) > 0);
foreach (lc, options)
{
deparseSeqOptElem(str, castNode(DefElem, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
}
static void deparseOptSeqOptList(StringInfo str, List *options)
{
if (list_length(options) > 0)
deparseSeqOptList(str, options);
}
static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
{
if (list_length(options) > 0)
{
appendStringInfoChar(str, '(');
deparseSeqOptList(str, options);
appendStringInfoChar(str, ')');
}
}
static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
{
switch (behavior)
{
case DROP_RESTRICT:
break;
case DROP_CASCADE:
appendStringInfoString(str, "CASCADE ");
break;
}
}
static void deparseAnyOperator(StringInfo str, List *op)
{
Assert(isOp(strVal(llast(op))));
if (list_length(op) == 2)
{
appendStringInfoString(str, quote_identifier(strVal(linitial(op))));
appendStringInfoChar(str, '.');
appendStringInfoString(str, strVal(llast(op)));
}
else if (list_length(op) == 1)
{
appendStringInfoString(str, strVal(llast(op)));
}
else
{
Assert(false);
}
}
static void deparseQualOp(StringInfo str, List *op)
{
if (list_length(op) == 1 && isOp(strVal(linitial(op))))
{
appendStringInfoString(str, strVal(linitial(op)));
}
else
{
appendStringInfoString(str, "OPERATOR(");
deparseAnyOperator(str, op);
appendStringInfoString(str, ")");
}
}
static void deparseSubqueryOp(StringInfo str, List *op)
{
if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~") == 0)
{
appendStringInfoString(str, "LIKE");
}
else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~") == 0)
{
appendStringInfoString(str, "NOT LIKE");
}
else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "~~*") == 0)
{
appendStringInfoString(str, "ILIKE");
}
else if (list_length(op) == 1 && strcmp(strVal(linitial(op)), "!~~*") == 0)
{
appendStringInfoString(str, "NOT ILIKE");
}
else if (list_length(op) == 1 && isOp(strVal(linitial(op))))
{
appendStringInfoString(str, strVal(linitial(op)));
}
else
{
appendStringInfoString(str, "OPERATOR(");
deparseAnyOperator(str, op);
appendStringInfoString(str, ")");
}
}
static void deparseGenericDefElemName(StringInfo str, const char *in)
{
Assert(in != NULL);
char *val = pstrdup(in);
for (unsigned char *p = (unsigned char *) val; *p; p++)
*p = pg_toupper(*p);
appendStringInfoString(str, val);
pfree(val);
}
static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
{
if (IsA(arg, TypeName)) {
deparseTypeName(str, castNode(TypeName, arg));
}
else if (IsA(arg, List)) {
List *l = castNode(List, arg);
Assert(list_length(l) == 1 || list_length(l) == 2);
if (list_length(l) == 2)
{
appendStringInfoString(str, "OPERATOR(");
deparseAnyOperator(str, l);
appendStringInfoChar(str, ')');
}
else if (list_length(l) == 1)
{
appendStringInfoString(str, strVal(linitial(l)));
}
}
else if (IsA(arg, Float) || IsA(arg, Integer)) {
deparseValue(str, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
}
else if (IsA(arg, String))
{
char *s = strVal(arg);
if (!is_operator_def_arg && IsA(arg, String) && strcmp(s, "none") == 0) {
appendStringInfoString(str, "NONE");
}
else if (isReservedKeyword(s)) {
appendStringInfoString(str, s);
}
else {
deparseStringLiteral(str, s);
}
}
else
{
Assert(false);
}
}
static void deparseDefinition(StringInfo str, List *options)
{
ListCell *lc = NULL;
appendStringInfoChar(str, '(');
foreach (lc, options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
appendStringInfoString(str, quote_identifier(def_elem->defname));
if (def_elem->arg != NULL) {
appendStringInfoString(str, " = ");
deparseDefArg(str, def_elem->arg, false);
}
if (lnext(options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparseOptDefinition(StringInfo str, List *options)
{
if (list_length(options) > 0)
{
appendStringInfoString(str, "WITH ");
deparseDefinition(str, options);
}
}
static void deparseCreateGenericOptions(StringInfo str, List *options)
{
ListCell *lc = NULL;
if (options == NULL)
return;
appendStringInfoString(str, "OPTIONS (");
foreach(lc, options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
appendStringInfoString(str, quote_identifier(def_elem->defname));
appendStringInfoChar(str, ' ');
deparseStringLiteral(str, strVal(def_elem->arg));
if (lnext(options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ")");
}
static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
{
if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
}
else if (strcmp(def_elem->defname, "strict") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "CALLED ON NULL INPUT");
}
else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "immutable") == 0)
{
appendStringInfoString(str, "IMMUTABLE");
}
else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "stable") == 0)
{
appendStringInfoString(str, "STABLE");
}
else if (strcmp(def_elem->defname, "volatility") == 0 && strcmp(strVal(def_elem->arg), "volatile") == 0)
{
appendStringInfoString(str, "VOLATILE");
}
else if (strcmp(def_elem->defname, "security") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "SECURITY DEFINER");
}
else if (strcmp(def_elem->defname, "security") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "SECURITY INVOKER");
}
else if (strcmp(def_elem->defname, "leakproof") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "LEAKPROOF");
}
else if (strcmp(def_elem->defname, "leakproof") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOT LEAKPROOF");
}
else if (strcmp(def_elem->defname, "cost") == 0)
{
appendStringInfoString(str, "COST ");
deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
}
else if (strcmp(def_elem->defname, "rows") == 0)
{
appendStringInfoString(str, "ROWS ");
deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
}
else if (strcmp(def_elem->defname, "support") == 0)
{
appendStringInfoString(str, "SUPPORT ");
deparseAnyName(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "set") == 0 && IsA(def_elem->arg, VariableSetStmt)) {
deparseVariableSetStmt(str, castNode(VariableSetStmt, def_elem->arg));
}
else if (strcmp(def_elem->defname, "parallel") == 0)
{
appendStringInfoString(str, "PARALLEL ");
appendStringInfoString(str, quote_identifier(strVal(def_elem->arg)));
}
else
{
Assert(false);
}
}
static void deparseNonReservedWordOrSconst(StringInfo str, const char *val)
{
if (strlen(val) == 0)
appendStringInfoString(str, "''");
else if (strlen(val) >= NAMEDATALEN)
deparseStringLiteral(str, val);
else
appendStringInfoString(str, quote_identifier(val));
}
static void deparseFuncAs(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
char *strval = strVal(lfirst(lc));
if (strstr(strval, "$$") == NULL)
{
appendStringInfoString(str, "$$");
appendStringInfoString(str, strval);
appendStringInfoString(str, "$$");
}
else
{
deparseStringLiteral(str, strval);
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseCreateFuncOptItem(StringInfo str, DefElem *def_elem)
{
ListCell *lc = NULL;
if (strcmp(def_elem->defname, "as") == 0)
{
appendStringInfoString(str, "AS ");
deparseFuncAs(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "language") == 0)
{
appendStringInfoString(str, "LANGUAGE ");
deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "transform") == 0)
{
List *l = castNode(List, def_elem->arg);
appendStringInfoString(str, "TRANSFORM ");
foreach (lc, l)
{
appendStringInfoString(str, "FOR TYPE ");
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
else if (strcmp(def_elem->defname, "window") == 0)
{
appendStringInfoString(str, "WINDOW");
}
else
{
deparseCommonFuncOptItem(str, def_elem);
}
}
static void deparseAlterGenericOptions(StringInfo str, List *options)
{
ListCell *lc = NULL;
appendStringInfoString(str, "OPTIONS (");
foreach(lc, options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
switch (def_elem->defaction)
{
case DEFELEM_UNSPEC:
appendStringInfoString(str, quote_identifier(def_elem->defname));
appendStringInfoChar(str, ' ');
deparseStringLiteral(str, strVal(def_elem->arg));
break;
case DEFELEM_SET:
appendStringInfoString(str, "SET ");
appendStringInfoString(str, quote_identifier(def_elem->defname));
appendStringInfoChar(str, ' ');
deparseStringLiteral(str, strVal(def_elem->arg));
break;
case DEFELEM_ADD:
appendStringInfoString(str, "ADD ");
appendStringInfoString(str, quote_identifier(def_elem->defname));
appendStringInfoChar(str, ' ');
deparseStringLiteral(str, strVal(def_elem->arg));
break;
case DEFELEM_DROP:
appendStringInfoString(str, "DROP ");
appendStringInfoString(str, quote_identifier(def_elem->defname));
break;
}
if (lnext(options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
static void deparseFuncName(StringInfo str, List *func_name)
{
ListCell *lc = NULL;
foreach(lc, func_name)
{
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
if (lnext(func_name, lc))
appendStringInfoChar(str, '.');
}
}
static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
{
ListCell *lc;
deparseFuncName(str, object_with_args->objname);
if (!object_with_args->args_unspecified)
{
appendStringInfoChar(str, '(');
List *objargs = object_with_args->objargs;
if (object_with_args->objfuncargs)
objargs = object_with_args->objfuncargs;
foreach(lc, objargs)
{
if (IsA(lfirst(lc), FunctionParameter))
deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
else
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
if (lnext(objargs, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
}
static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
{
ListCell *lc;
foreach(lc, l)
{
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseOperatorWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
{
deparseAnyOperator(str, object_with_args->objname);
Assert(list_length(object_with_args->objargs) == 2);
appendStringInfoChar(str, '(');
if (linitial(object_with_args->objargs) == NULL)
appendStringInfoString(str, "NONE");
else
deparseTypeName(str, castNode(TypeName, linitial(object_with_args->objargs)));
appendStringInfoString(str, ", ");
if (lsecond(object_with_args->objargs) == NULL)
appendStringInfoString(str, "NONE");
else
deparseTypeName(str, castNode(TypeName, lsecond(object_with_args->objargs)));
appendStringInfoChar(str, ')');
}
static void deparseAggrArgs(StringInfo str, List *aggr_args)
{
Assert(list_length(aggr_args) == 2);
ListCell *lc = NULL;
List *args = linitial(aggr_args);
int order_by_pos = intVal(lsecond(aggr_args));
appendStringInfoChar(str, '(');
if (args == NULL)
{
appendStringInfoChar(str, '*');
}
else
{
foreach(lc, args)
{
if (foreach_current_index(lc) == order_by_pos)
{
if (foreach_current_index(lc) > 0)
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "ORDER BY ");
}
else if (foreach_current_index(lc) > 0)
{
appendStringInfoString(str, ", ");
}
deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
}
if (order_by_pos == list_length(args))
{
appendStringInfoString(str, " ORDER BY ");
deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
}
}
appendStringInfoChar(str, ')');
}
static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
{
ListCell *lc = NULL;
deparseFuncName(str, object_with_args->objname);
appendStringInfoChar(str, '(');
if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
{
appendStringInfoChar(str, '*');
}
else
{
List *objargs = object_with_args->objargs;
if (object_with_args->objfuncargs)
objargs = object_with_args->objfuncargs;
foreach(lc, objargs)
{
if (IsA(lfirst(lc), FunctionParameter))
deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
else
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
if (lnext(objargs, lc))
appendStringInfoString(str, ", ");
}
}
appendStringInfoChar(str, ')');
}
static void deparseColumnList(StringInfo str, List *columns)
{
ListCell *lc = NULL;
foreach(lc, columns)
{
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
if (lnext(columns, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseOptTemp(StringInfo str, char relpersistence)
{
switch (relpersistence)
{
case RELPERSISTENCE_PERMANENT:
break;
case RELPERSISTENCE_UNLOGGED:
appendStringInfoString(str, "UNLOGGED ");
break;
case RELPERSISTENCE_TEMP:
appendStringInfoString(str, "TEMPORARY ");
break;
default:
Assert(false);
break;
}
}
static void deparseRelationExprList(StringInfo str, List *relation_exprs)
{
ListCell *lc = NULL;
foreach(lc, relation_exprs)
{
deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
if (lnext(relation_exprs, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseHandlerName(StringInfo str, List *handler_name)
{
ListCell *lc = NULL;
foreach(lc, handler_name)
{
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc))));
if (lnext(handler_name, lc))
appendStringInfoChar(str, '.');
}
}
static void deparseFdwOptions(StringInfo str, List *fdw_options)
{
ListCell *lc = NULL;
foreach (lc, fdw_options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "HANDLER ");
deparseHandlerName(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "handler") == 0 && def_elem->arg == NULL)
{
appendStringInfoString(str, "NO HANDLER ");
}
else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "VALIDATOR ");
deparseHandlerName(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "validator") == 0 && def_elem->arg == NULL)
{
appendStringInfoString(str, "NO VALIDATOR ");
}
else
{
Assert(false);
}
if (lnext(fdw_options, lc))
appendStringInfoChar(str, ' ');
}
}
static void deparseTypeList(StringInfo str, List *type_list)
{
ListCell *lc = NULL;
foreach(lc, type_list)
{
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
if (lnext(type_list, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseOptBooleanOrString(StringInfo str, char *s)
{
if (s == NULL)
return; else if (strcmp(s, "true") == 0)
appendStringInfoString(str, "TRUE");
else if (strcmp(s, "false") == 0)
appendStringInfoString(str, "FALSE");
else if (strcmp(s, "on") == 0)
appendStringInfoString(str, "ON");
else if (strcmp(s, "off") == 0)
appendStringInfoString(str, "OFF");
else
deparseNonReservedWordOrSconst(str, s);
}
static void deparseOptBoolean(StringInfo str, Node *node)
{
if (node == NULL)
{
return;
}
switch (nodeTag(node))
{
case T_String:
appendStringInfo(str, " %s", strVal(node));
break;
case T_Integer:
appendStringInfo(str, " %d", intVal(node));
break;
case T_Boolean:
appendStringInfo(str, " %s", boolVal(node) ? "TRUE" : "FALSE");
break;
default:
Assert(false);
break;
}
}
bool optBooleanValue(Node *node)
{
if (node == NULL)
{
return true;
}
switch (nodeTag(node))
{
case T_String: {
char lower[4];
strncpy(lower, strVal(node), 4);
lower[3] = 0;
if (strcmp(lower, "on") == 0) {
return true;
} else if (strcmp(lower, "off") == 0) {
return false;
}
return false;
}
case T_Integer:
return intVal(node) != 0;
case T_Boolean:
return boolVal(node);
default:
Assert(false);
return false;
}
}
static void deparseVarName(StringInfo str, char *s)
{
deparseColId(str, s);
}
static void deparseVarList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
if (IsA(lfirst(lc), ParamRef))
{
deparseParamRef(str, castNode(ParamRef, lfirst(lc)));
}
else if (IsA(lfirst(lc), A_Const))
{
A_Const *a_const = castNode(A_Const, lfirst(lc));
if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
deparseNumericOnly(str, (union ValUnion *) &a_const->val);
else if (IsA(&a_const->val, String))
deparseOptBooleanOrString(str, strVal(&a_const->val));
else
Assert(false);
}
else if (IsA(lfirst(lc), TypeCast))
{
deparseTypeCast(str, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
}
else
{
Assert(false);
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseTransactionModeList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach (lc, l)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "transaction_isolation") == 0)
{
char *s = strVal(&castNode(A_Const, def_elem->arg)->val);
appendStringInfoString(str, "ISOLATION LEVEL ");
if (strcmp(s, "read uncommitted") == 0)
appendStringInfoString(str, "READ UNCOMMITTED");
else if (strcmp(s, "read committed") == 0)
appendStringInfoString(str, "READ COMMITTED");
else if (strcmp(s, "repeatable read") == 0)
appendStringInfoString(str, "REPEATABLE READ");
else if (strcmp(s, "serializable") == 0)
appendStringInfoString(str, "SERIALIZABLE");
else
Assert(false);
}
else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
{
appendStringInfoString(str, "READ ONLY");
}
else if (strcmp(def_elem->defname, "transaction_read_only") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
{
appendStringInfoString(str, "READ WRITE");
}
else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 1)
{
appendStringInfoString(str, "DEFERRABLE");
}
else if (strcmp(def_elem->defname, "transaction_deferrable") == 0 && intVal(&castNode(A_Const, def_elem->arg)->val) == 0)
{
appendStringInfoString(str, "NOT DEFERRABLE");
}
else
{
Assert(false);
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach (lc, l)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
{
appendStringInfoString(str, "RESTART");
}
else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "RESTART ");
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "generated") == 0)
{
appendStringInfoString(str, "SET GENERATED ");
if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_ALWAYS)
appendStringInfoString(str, "ALWAYS");
else if (intVal(def_elem->arg) == ATTRIBUTE_IDENTITY_BY_DEFAULT)
appendStringInfoString(str, "BY DEFAULT");
else
Assert(false);
}
else
{
appendStringInfoString(str, "SET ");
deparseSeqOptElem(str, def_elem);
}
if (lnext(l, lc))
appendStringInfoChar(str, ' ');
}
}
static void deparseRelOptions(StringInfo str, List *l)
{
ListCell *lc = NULL;
appendStringInfoChar(str, '(');
foreach(lc, l)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (def_elem->defnamespace != NULL)
{
appendStringInfoString(str, quote_identifier(def_elem->defnamespace));
appendStringInfoChar(str, '.');
}
if (def_elem->defname != NULL)
appendStringInfoString(str, quote_identifier(def_elem->defname));
if (def_elem->defname != NULL && def_elem->arg != NULL)
appendStringInfoChar(str, '=');
if (def_elem->arg != NULL)
deparseDefArg(str, def_elem->arg, false);
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparseOptWith(StringInfo str, List *l)
{
ListCell *lc = NULL;
if (list_length(l) > 0)
{
appendStringInfoString(str, "WITH ");
deparseRelOptions(str, l);
appendStringInfoChar(str, ' ');
}
}
static void deparseTargetList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
ResTarget *res_target = castNode(ResTarget, lfirst(lc));
if (res_target->val == NULL)
elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
else if (IsA(res_target->val, ColumnRef))
deparseColumnRef(str, castNode(ColumnRef, res_target->val));
else
deparseExpr(str, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
if (res_target->name != NULL) {
appendStringInfoString(str, " AS ");
appendStringInfoString(str, quote_identifier(res_target->name));
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseInsertColumnList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
ResTarget *res_target = castNode(ResTarget, lfirst(lc));
Assert(res_target->name != NULL);
appendStringInfoString(str, quote_identifier(res_target->name));
deparseOptIndirection(str, res_target->indirection, 0);
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseXmlAttributeList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
ResTarget *res_target = castNode(ResTarget, lfirst(lc));
Assert(res_target->val != NULL);
deparseExpr(str, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
if (res_target->name != NULL)
{
appendStringInfoString(str, " AS ");
appendStringInfoString(str, quote_identifier(res_target->name));
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseXmlNamespaceList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
ResTarget *res_target = castNode(ResTarget, lfirst(lc));
Assert(res_target->val != NULL);
if (res_target->name == NULL)
appendStringInfoString(str, "DEFAULT ");
deparseExpr(str, res_target->val, DEPARSE_NODE_CONTEXT_NONE );
if (res_target->name != NULL)
{
appendStringInfoString(str, " AS ");
appendStringInfoString(str, quote_identifier(res_target->name));
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseTableRef(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_RangeVar:
deparseRangeVar(str, castNode(RangeVar, node), DEPARSE_NODE_CONTEXT_NONE);
break;
case T_RangeTableSample:
deparseRangeTableSample(str, castNode(RangeTableSample, node));
break;
case T_RangeFunction:
deparseRangeFunction(str, castNode(RangeFunction, node));
break;
case T_RangeTableFunc:
deparseRangeTableFunc(str, castNode(RangeTableFunc, node));
break;
case T_RangeSubselect:
deparseRangeSubselect(str, castNode(RangeSubselect, node));
break;
case T_JoinExpr:
deparseJoinExpr(str, castNode(JoinExpr, node));
break;
case T_JsonTable:
deparseJsonTable(str, castNode(JsonTable, node));
break;
default:
Assert(false);
}
}
static void deparseFromList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseTableRef(str, lfirst(lc));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseFromClause(StringInfo str, List *l)
{
if (list_length(l) > 0)
{
appendStringInfoString(str, "FROM ");
deparseFromList(str, l);
appendStringInfoChar(str, ' ');
}
}
static void deparseWhereClause(StringInfo str, Node *node)
{
if (node != NULL)
{
appendStringInfoString(str, "WHERE ");
deparseExpr(str, node, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
}
static void deparseWhereOrCurrentClause(StringInfo str, Node *node)
{
if (node == NULL)
return;
appendStringInfoString(str, "WHERE ");
if (IsA(node, CurrentOfExpr)) {
CurrentOfExpr *current_of_expr = castNode(CurrentOfExpr, node);
appendStringInfoString(str, "CURRENT OF ");
appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
} else {
deparseExpr(str, node, DEPARSE_NODE_CONTEXT_A_EXPR);
}
appendStringInfoChar(str, ' ');
}
static void deparseGroupByList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
if (IsA(lfirst(lc), GroupingSet))
deparseGroupingSet(str, castNode(GroupingSet, lfirst(lc)));
else
deparseExpr(str, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseSetTarget(StringInfo str, ResTarget *res_target)
{
Assert(res_target->name != NULL);
deparseColId(str, res_target->name);
deparseOptIndirection(str, res_target->indirection, 0);
}
static void deparseAnyNameList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseAnyName(str, castNode(List, lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseNameList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseColId(str, strVal(lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseOptSortClause(StringInfo str, List *l)
{
ListCell *lc = NULL;
if (list_length(l) > 0)
{
appendStringInfoString(str, "ORDER BY ");
foreach(lc, l)
{
deparseSortBy(str, castNode(SortBy, lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
}
}
static void deparseFuncArgExpr(StringInfo str, Node *node)
{
if (IsA(node, NamedArgExpr))
{
NamedArgExpr *named_arg_expr = castNode(NamedArgExpr, node);
appendStringInfoString(str, named_arg_expr->name);
appendStringInfoString(str, " := ");
deparseExpr(str, (Node *) named_arg_expr->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
}
else
{
deparseExpr(str, node, DEPARSE_NODE_CONTEXT_A_EXPR);
}
}
static void deparseSetClauseList(StringInfo str, List *target_list)
{
ListCell *lc;
ListCell *lc2;
int skip_next_n_elems = 0;
Assert(list_length(target_list) > 0);
foreach(lc, target_list)
{
if (skip_next_n_elems > 0)
{
skip_next_n_elems--;
continue;
}
if (foreach_current_index(lc) != 0)
appendStringInfoString(str, ", ");
ResTarget *res_target = castNode(ResTarget, lfirst(lc));
Assert(res_target->val != NULL);
if (IsA(res_target->val, MultiAssignRef))
{
MultiAssignRef *r = castNode(MultiAssignRef, res_target->val);
appendStringInfoString(str, "(");
for_each_cell(lc2, target_list, lc)
{
deparseSetTarget(str, castNode(ResTarget, lfirst(lc2)));
if (foreach_current_index(lc2) == r->ncolumns - 1) break;
else if (lnext(target_list, lc2))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") = ");
deparseExpr(str, r->source, DEPARSE_NODE_CONTEXT_A_EXPR);
skip_next_n_elems = r->ncolumns - 1;
}
else
{
deparseSetTarget(str, res_target);
appendStringInfoString(str, " = ");
deparseExpr(str, res_target->val, DEPARSE_NODE_CONTEXT_A_EXPR);
}
}
}
static void deparseFuncExprWindowless(StringInfo str, Node* node)
{
switch (nodeTag(node))
{
case T_FuncCall:
deparseFuncCall(str, castNode(FuncCall, node), DEPARSE_NODE_CONTEXT_NONE );
break;
case T_SQLValueFunction:
deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
break;
case T_TypeCast:
deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_FUNC_EXPR);
break;
case T_CoalesceExpr:
deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
break;
case T_MinMaxExpr:
deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
break;
case T_XmlExpr:
deparseXmlExpr(str, castNode(XmlExpr, node), DEPARSE_NODE_CONTEXT_NONE );
break;
case T_XmlSerialize:
deparseXmlSerialize(str, castNode(XmlSerialize, node));
break;
default:
Assert(false);
}
}
static void deparseOptCollate(StringInfo str, List *l)
{
if (list_length(l) > 0)
{
appendStringInfoString(str, "COLLATE ");
deparseAnyName(str, l);
appendStringInfoChar(str, ' ');
}
}
static void deparseIndexElem(StringInfo str, IndexElem* index_elem)
{
if (index_elem->name != NULL)
{
deparseColId(str, index_elem->name);
appendStringInfoChar(str, ' ');
}
else if (index_elem->expr != NULL)
{
switch (nodeTag(index_elem->expr))
{
case T_FuncCall: case T_SQLValueFunction: case T_CoalesceExpr: case T_MinMaxExpr: case T_XmlExpr: case T_XmlSerialize: deparseFuncExprWindowless(str, index_elem->expr);
appendStringInfoString(str, " ");
break;
default:
appendStringInfoChar(str, '(');
deparseExpr(str, index_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
}
else
{
Assert(false);
}
deparseOptCollate(str, index_elem->collation);
if (list_length(index_elem->opclass) > 0)
{
deparseAnyName(str, index_elem->opclass);
if (list_length(index_elem->opclassopts) > 0)
deparseRelOptions(str, index_elem->opclassopts);
appendStringInfoChar(str, ' ');
}
switch (index_elem->ordering)
{
case SORTBY_DEFAULT:
break;
case SORTBY_ASC:
appendStringInfoString(str, "ASC ");
break;
case SORTBY_DESC:
appendStringInfoString(str, "DESC ");
break;
case SORTBY_USING:
Assert(false);
break;
}
switch (index_elem->nulls_ordering)
{
case SORTBY_NULLS_DEFAULT:
break;
case SORTBY_NULLS_FIRST:
appendStringInfoString(str, "NULLS FIRST ");
break;
case SORTBY_NULLS_LAST:
appendStringInfoString(str, "NULLS LAST ");
break;
}
removeTrailingSpace(str);
}
static void deparseQualifiedNameList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseRangeVar(str, castNode(RangeVar, lfirst(lc)), DEPARSE_NODE_CONTEXT_NONE);
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseOptInherit(StringInfo str, List *l)
{
if (list_length(l) > 0)
{
appendStringInfoString(str, "INHERITS (");
deparseQualifiedNameList(str, l);
appendStringInfoString(str, ") ");
}
}
static void deparsePrivilegeTarget(StringInfo str, GrantTargetType targtype, ObjectType objtype, List *objs)
{
switch (targtype)
{
case ACL_TARGET_OBJECT:
switch (objtype)
{
case OBJECT_TABLE:
deparseQualifiedNameList(str, objs);
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
deparseQualifiedNameList(str, objs);
break;
case OBJECT_FDW:
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
deparseNameList(str, objs);
break;
case OBJECT_FOREIGN_SERVER:
appendStringInfoString(str, "FOREIGN SERVER ");
deparseNameList(str, objs);
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
deparseFunctionWithArgtypesList(str, objs);
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
deparseFunctionWithArgtypesList(str, objs);
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
deparseFunctionWithArgtypesList(str, objs);
break;
case OBJECT_DATABASE:
appendStringInfoString(str, "DATABASE ");
deparseNameList(str, objs);
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
deparseAnyNameList(str, objs);
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
deparseNameList(str, objs);
break;
case OBJECT_LARGEOBJECT:
appendStringInfoString(str, "LARGE OBJECT ");
deparseNumericOnlyList(str, objs);
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
deparseNameList(str, objs);
break;
case OBJECT_TABLESPACE:
appendStringInfoString(str, "TABLESPACE ");
deparseNameList(str, objs);
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
deparseAnyNameList(str, objs);
break;
default:
Assert(false);
break;
}
break;
case ACL_TARGET_ALL_IN_SCHEMA:
switch (objtype)
{
case OBJECT_TABLE:
appendStringInfoString(str, "ALL TABLES IN SCHEMA ");
deparseNameList(str, objs);
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "ALL SEQUENCES IN SCHEMA ");
deparseNameList(str, objs);
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "ALL FUNCTIONS IN SCHEMA ");
deparseNameList(str, objs);
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "ALL PROCEDURES IN SCHEMA ");
deparseNameList(str, objs);
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ALL ROUTINES IN SCHEMA ");
deparseNameList(str, objs);
break;
default:
Assert(false);
break;
}
break;
case ACL_TARGET_DEFAULTS: switch (objtype)
{
case OBJECT_TABLE:
appendStringInfoString(str, "TABLES");
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTIONS");
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCES");
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPES");
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMAS");
break;
default:
Assert(false);
break;
}
break;
}
}
static void deparseOpclassItemList(StringInfo str, List *items)
{
ListCell *lc = NULL;
foreach (lc, items)
{
deparseCreateOpClassItem(str, castNode(CreateOpClassItem, lfirst(lc)));
if (lnext(items, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseCreatedbOptList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach (lc, l)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "connection_limit") == 0)
appendStringInfoString(str, "CONNECTION LIMIT");
else
deparseGenericDefElemName(str, def_elem->defname);
appendStringInfoChar(str, ' ');
if (def_elem->arg == NULL)
appendStringInfoString(str, "DEFAULT");
else if (IsA(def_elem->arg, Integer))
deparseSignedIconst(str, def_elem->arg);
else if (IsA(def_elem->arg, String))
deparseOptBooleanOrString(str, strVal(def_elem->arg));
if (lnext(l, lc))
appendStringInfoChar(str, ' ');
}
}
static void deparseUtilityOptionList(StringInfo str, List *options)
{
ListCell *lc = NULL;
char *defname = NULL;
if (list_length(options) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
deparseGenericDefElemName(str, def_elem->defname);
if (def_elem->arg != NULL)
{
appendStringInfoChar(str, ' ');
if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
else if (IsA(def_elem->arg, String))
deparseOptBooleanOrString(str, strVal(def_elem->arg));
else
Assert(false);
}
if (lnext(options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
}
static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
{
const ListCell *lc = NULL;
const ListCell *lc2 = NULL;
if (stmt->withClause)
{
deparseWithClause(str, stmt->withClause);
appendStringInfoChar(str, ' ');
}
switch (stmt->op) {
case SETOP_NONE:
if (list_length(stmt->valuesLists) > 0)
{
const ListCell *lc;
appendStringInfoString(str, "VALUES ");
foreach(lc, stmt->valuesLists)
{
appendStringInfoChar(str, '(');
deparseExprList(str, lfirst(lc));
appendStringInfoChar(str, ')');
if (lnext(stmt->valuesLists, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
break;
}
appendStringInfoString(str, "SELECT ");
if (list_length(stmt->targetList) > 0)
{
if (stmt->distinctClause != NULL)
{
appendStringInfoString(str, "DISTINCT ");
if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
{
appendStringInfoString(str, "ON (");
deparseExprList(str, stmt->distinctClause);
appendStringInfoString(str, ") ");
}
}
deparseTargetList(str, stmt->targetList);
appendStringInfoChar(str, ' ');
}
if (stmt->intoClause != NULL)
{
appendStringInfoString(str, "INTO ");
deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
deparseIntoClause(str, stmt->intoClause);
appendStringInfoChar(str, ' ');
}
deparseFromClause(str, stmt->fromClause);
deparseWhereClause(str, stmt->whereClause);
if (list_length(stmt->groupClause) > 0)
{
appendStringInfoString(str, "GROUP BY ");
if (stmt->groupDistinct)
appendStringInfoString(str, "DISTINCT ");
deparseGroupByList(str, stmt->groupClause);
appendStringInfoChar(str, ' ');
}
if (stmt->havingClause != NULL)
{
appendStringInfoString(str, "HAVING ");
deparseExpr(str, stmt->havingClause, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
if (stmt->windowClause != NULL)
{
appendStringInfoString(str, "WINDOW ");
foreach(lc, stmt->windowClause)
{
WindowDef *window_def = castNode(WindowDef, lfirst(lc));
Assert(window_def->name != NULL);
appendStringInfoString(str, window_def->name);
appendStringInfoString(str, " AS ");
deparseWindowDef(str, window_def);
if (lnext(stmt->windowClause, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
}
break;
case SETOP_UNION:
case SETOP_INTERSECT:
case SETOP_EXCEPT:
{
bool need_larg_parens =
list_length(stmt->larg->sortClause) > 0 ||
stmt->larg->limitOffset != NULL ||
stmt->larg->limitCount != NULL ||
list_length(stmt->larg->lockingClause) > 0 ||
stmt->larg->withClause != NULL ||
stmt->larg->op != SETOP_NONE;
bool need_rarg_parens =
list_length(stmt->rarg->sortClause) > 0 ||
stmt->rarg->limitOffset != NULL ||
stmt->rarg->limitCount != NULL ||
list_length(stmt->rarg->lockingClause) > 0 ||
stmt->rarg->withClause != NULL ||
stmt->rarg->op != SETOP_NONE;
if (need_larg_parens)
appendStringInfoChar(str, '(');
deparseSelectStmt(str, stmt->larg);
if (need_larg_parens)
appendStringInfoChar(str, ')');
switch (stmt->op)
{
case SETOP_UNION:
appendStringInfoString(str, " UNION ");
break;
case SETOP_INTERSECT:
appendStringInfoString(str, " INTERSECT ");
break;
case SETOP_EXCEPT:
appendStringInfoString(str, " EXCEPT ");
break;
default:
Assert(false);
}
if (stmt->all)
appendStringInfoString(str, "ALL ");
if (need_rarg_parens)
appendStringInfoChar(str, '(');
deparseSelectStmt(str, stmt->rarg);
if (need_rarg_parens)
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
}
break;
}
deparseOptSortClause(str, stmt->sortClause);
if (stmt->limitCount != NULL)
{
if (stmt->limitOption == LIMIT_OPTION_COUNT)
appendStringInfoString(str, "LIMIT ");
else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
appendStringInfoString(str, "FETCH FIRST ");
if (IsA(stmt->limitCount, A_Const) && castNode(A_Const, stmt->limitCount)->isnull)
appendStringInfoString(str, "ALL");
else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
deparseCExpr(str, stmt->limitCount);
else
deparseExpr(str, stmt->limitCount, DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoChar(str, ' ');
if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
appendStringInfoString(str, "ROWS WITH TIES ");
}
if (stmt->limitOffset != NULL)
{
appendStringInfoString(str, "OFFSET ");
deparseExpr(str, stmt->limitOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
if (list_length(stmt->lockingClause) > 0)
{
foreach(lc, stmt->lockingClause)
{
deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
if (lnext(stmt->lockingClause, lc))
appendStringInfoString(str, " ");
}
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseIntoClause(StringInfo str, IntoClause *into_clause)
{
ListCell *lc;
deparseRangeVar(str, into_clause->rel, DEPARSE_NODE_CONTEXT_NONE);
if (list_length(into_clause->colNames) > 0)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, into_clause->colNames);
appendStringInfoChar(str, ')');
}
appendStringInfoChar(str, ' ');
if (into_clause->accessMethod != NULL)
{
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(into_clause->accessMethod));
appendStringInfoChar(str, ' ');
}
deparseOptWith(str, into_clause->options);
switch (into_clause->onCommit)
{
case ONCOMMIT_NOOP:
break;
case ONCOMMIT_PRESERVE_ROWS:
appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
break;
case ONCOMMIT_DELETE_ROWS:
appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
break;
case ONCOMMIT_DROP:
appendStringInfoString(str, "ON COMMIT DROP ");
break;
}
if (into_clause->tableSpaceName != NULL)
{
appendStringInfoString(str, "TABLESPACE ");
appendStringInfoString(str, quote_identifier(into_clause->tableSpaceName));
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeContext context)
{
if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "ONLY ");
if (range_var->catalogname != NULL)
{
appendStringInfoString(str, quote_identifier(range_var->catalogname));
appendStringInfoChar(str, '.');
}
if (range_var->schemaname != NULL)
{
appendStringInfoString(str, quote_identifier(range_var->schemaname));
appendStringInfoChar(str, '.');
}
Assert(range_var->relname != NULL);
appendStringInfoString(str, quote_identifier(range_var->relname));
appendStringInfoChar(str, ' ');
if (range_var->alias != NULL)
{
if (context == DEPARSE_NODE_CONTEXT_INSERT_RELATION)
appendStringInfoString(str, "AS ");
deparseAlias(str, range_var->alias);
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
{
if (raw_stmt->stmt == NULL)
elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
deparseStmt(str, raw_stmt->stmt);
}
static void deparseAlias(StringInfo str, Alias *alias)
{
appendStringInfoString(str, quote_identifier(alias->aliasname));
if (list_length(alias->colnames) > 0)
{
const ListCell *lc = NULL;
appendStringInfoChar(str, '(');
deparseNameList(str, alias->colnames);
appendStringInfoChar(str, ')');
}
}
static void deparseAConst(StringInfo str, A_Const *a_const)
{
union ValUnion *val = a_const->isnull ? NULL : &a_const->val;
deparseValue(str, val, DEPARSE_NODE_CONTEXT_CONSTANT);
}
static void deparseFuncCall(StringInfo str, FuncCall *func_call, DeparseNodeContext context)
{
const ListCell *lc = NULL;
Assert(list_length(func_call->funcname) > 0);
if (list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
list_length(func_call->args) == 4)
{
appendStringInfoString(str, "OVERLAY(");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " PLACING ");
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FROM ");
deparseExpr(str, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FOR ");
deparseExpr(str, lfourth(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
{
Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
appendStringInfoString(str, "SUBSTRING(");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FROM ");
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
if (list_length(func_call->args) == 3)
{
appendStringInfoString(str, " FOR ");
deparseExpr(str, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
}
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
list_length(func_call->args) == 2)
{
appendStringInfoString(str, "POSITION(");
deparseBExpr(str, lsecond(func_call->args));
appendStringInfoString(str, " IN ");
deparseBExpr(str, linitial(func_call->args));
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
list_length(func_call->args) == 3)
{
appendStringInfoString(str, "overlay(");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " placing ");
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " from ");
deparseExpr(str, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
list_length(func_call->args) == 1)
{
appendStringInfoString(str, "collation for (");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
list_length(func_call->args) == 2)
{
appendStringInfoString(str, "extract (");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FROM ");
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
list_length(func_call->args) == 4)
{
appendStringInfoChar(str, '(');
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ", ");
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
appendStringInfoString(str, "overlaps ");
appendStringInfoChar(str, '(');
deparseExpr(str, lthird(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ", ");
deparseExpr(str, lfourth(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
(
strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
))
{
Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
appendStringInfoString(str, "TRIM (");
if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
appendStringInfoString(str, "LEADING ");
else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
appendStringInfoString(str, "BOTH ");
else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
appendStringInfoString(str, "TRAILING ");
if (list_length(func_call->args) == 2)
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FROM ");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
list_length(func_call->args) > 0 &&
list_length(func_call->args) <= 2)
{
Expr* e;
bool isLocal = list_length(func_call->args) == 1;
if (isLocal)
e = linitial(func_call->args);
else
e = lsecond(func_call->args);
if (context != DEPARSE_NODE_CONTEXT_A_EXPR) {
appendStringInfoChar(str, '(');
}
if (IsA(e, A_Expr)) {
appendStringInfoChar(str, '(');
}
deparseExpr(str, (Node*) e, DEPARSE_NODE_CONTEXT_A_EXPR);
if (IsA(e, A_Expr)) {
appendStringInfoChar(str, ')');
}
if (isLocal)
appendStringInfoString(str, " AT LOCAL");
else {
appendStringInfoString(str, " AT TIME ZONE ");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
}
if (context != DEPARSE_NODE_CONTEXT_A_EXPR) {
appendStringInfoChar(str, ')');
}
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
{
Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
appendStringInfoString(str, "normalize (");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
if (list_length(func_call->args) == 2)
{
appendStringInfoString(str, ", ");
Assert(IsA(lsecond(func_call->args), A_Const));
A_Const *aconst = lsecond(func_call->args);
deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
}
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
{
Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " IS ");
if (list_length(func_call->args) == 2)
{
Assert(IsA(lsecond(func_call->args), A_Const));
A_Const *aconst = lsecond(func_call->args);
deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
}
appendStringInfoString(str, " NORMALIZED ");
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
list_length(func_call->args) == 2)
{
appendStringInfoString(str, "xmlexists (");
deparseExpr(str, linitial(func_call->args), DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoString(str, " PASSING ");
deparseExpr(str, lsecond(func_call->args), DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoChar(str, ')');
return;
} else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
list_length(func_call->funcname) == 2 &&
strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
strcmp(strVal(lsecond(func_call->funcname)), "system_user") == 0)
{
appendStringInfoString(str, "SYSTEM_USER");
return;
}
deparseFuncName(str, func_call->funcname);
appendStringInfoChar(str, '(');
if (func_call->agg_distinct)
appendStringInfoString(str, "DISTINCT ");
if (func_call->agg_star)
{
appendStringInfoChar(str, '*');
}
else if (list_length(func_call->args) > 0)
{
foreach(lc, func_call->args)
{
if (func_call->func_variadic && !lnext(func_call->args, lc))
appendStringInfoString(str, "VARIADIC ");
deparseFuncArgExpr(str, lfirst(lc));
if (lnext(func_call->args, lc))
appendStringInfoString(str, ", ");
}
}
appendStringInfoChar(str, ' ');
if (func_call->agg_order != NULL && !func_call->agg_within_group)
{
deparseOptSortClause(str, func_call->agg_order);
}
removeTrailingSpace(str);
appendStringInfoString(str, ") ");
if (func_call->agg_order != NULL && func_call->agg_within_group)
{
appendStringInfoString(str, "WITHIN GROUP (");
deparseOptSortClause(str, func_call->agg_order);
removeTrailingSpace(str);
appendStringInfoString(str, ") ");
}
if (func_call->agg_filter)
{
appendStringInfoString(str, "FILTER (WHERE ");
deparseExpr(str, func_call->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
if (func_call->over)
{
appendStringInfoString(str, "OVER ");
if (func_call->over->name)
appendStringInfoString(str, func_call->over->name);
else
deparseWindowDef(str, func_call->over);
}
removeTrailingSpace(str);
}
static void deparseWindowDef(StringInfo str, WindowDef* window_def)
{
ListCell *lc;
appendStringInfoChar(str, '(');
if (window_def->refname != NULL)
{
appendStringInfoString(str, quote_identifier(window_def->refname));
appendStringInfoChar(str, ' ');
}
if (list_length(window_def->partitionClause) > 0)
{
appendStringInfoString(str, "PARTITION BY ");
deparseExprList(str, window_def->partitionClause);
appendStringInfoChar(str, ' ');
}
deparseOptSortClause(str, window_def->orderClause);
if (window_def->frameOptions & FRAMEOPTION_NONDEFAULT)
{
if (window_def->frameOptions & FRAMEOPTION_RANGE)
appendStringInfoString(str, "RANGE ");
else if (window_def->frameOptions & FRAMEOPTION_ROWS)
appendStringInfoString(str, "ROWS ");
else if (window_def->frameOptions & FRAMEOPTION_GROUPS)
appendStringInfoString(str, "GROUPS ");
if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
appendStringInfoString(str, "BETWEEN ");
if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
{
appendStringInfoString(str, "UNBOUNDED PRECEDING ");
}
else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
{
Assert(false); }
else if (window_def->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
{
appendStringInfoString(str, "CURRENT ROW ");
}
else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING)
{
Assert(window_def->startOffset != NULL);
deparseExpr(str, window_def->startOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " PRECEDING ");
}
else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
{
Assert(window_def->startOffset != NULL);
deparseExpr(str, window_def->startOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FOLLOWING ");
}
if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
{
appendStringInfoString(str, "AND ");
if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
{
Assert(false); }
else if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
{
appendStringInfoString(str, "UNBOUNDED FOLLOWING ");
}
else if (window_def->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
{
appendStringInfoString(str, "CURRENT ROW ");
}
else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)
{
Assert(window_def->endOffset != NULL);
deparseExpr(str, window_def->endOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " PRECEDING ");
}
else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
{
Assert(window_def->endOffset != NULL);
deparseExpr(str, window_def->endOffset, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " FOLLOWING ");
}
}
if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW)
appendStringInfoString(str, "EXCLUDE CURRENT ROW ");
else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_GROUP)
appendStringInfoString(str, "EXCLUDE GROUP ");
else if (window_def->frameOptions & FRAMEOPTION_EXCLUDE_TIES)
appendStringInfoString(str, "EXCLUDE TIES ");
}
removeTrailingSpace(str);
appendStringInfoChar(str, ')');
}
static void deparseColumnRef(StringInfo str, ColumnRef* column_ref)
{
Assert(list_length(column_ref->fields) >= 1);
if (IsA(linitial(column_ref->fields), A_Star))
deparseAStar(str, castNode(A_Star, linitial(column_ref->fields)));
else if (IsA(linitial(column_ref->fields), String))
deparseColLabel(str, strVal(linitial(column_ref->fields)));
deparseOptIndirection(str, column_ref->fields, 1);
}
static void deparseSubLink(StringInfo str, SubLink* sub_link)
{
switch (sub_link->subLinkType) {
case EXISTS_SUBLINK:
appendStringInfoString(str, "EXISTS (");
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case ALL_SUBLINK:
deparseExpr(str, sub_link->testexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, sub_link->operName);
appendStringInfoString(str, " ALL (");
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case ANY_SUBLINK:
deparseExpr(str, sub_link->testexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
if (list_length(sub_link->operName) > 0)
{
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, sub_link->operName);
appendStringInfoString(str, " ANY ");
}
else
{
appendStringInfoString(str, " IN ");
}
appendStringInfoChar(str, '(');
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case ROWCOMPARE_SUBLINK:
Assert(false);
return;
case EXPR_SUBLINK:
appendStringInfoString(str, "(");
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case MULTIEXPR_SUBLINK:
Assert(false);
return;
case ARRAY_SUBLINK:
appendStringInfoString(str, "ARRAY(");
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case CTE_SUBLINK:
Assert(false);
return;
}
}
static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
{
ListCell *lc;
char *name;
bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, BooleanTest) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, BooleanTest) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
switch (a_expr->kind) {
case AEXPR_OP:
{
if (a_expr->lexpr != NULL)
{
if (need_lexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->lexpr, context);
if (need_lexpr_parens)
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
}
deparseQualOp(str, a_expr->name);
if (a_expr->rexpr != NULL)
{
appendStringInfoChar(str, ' ');
if (need_rexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->rexpr, context);
if (need_rexpr_parens)
appendStringInfoChar(str, ')');
}
}
return;
case AEXPR_OP_ANY:
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, a_expr->name);
appendStringInfoString(str, " ANY(");
deparseExpr(str, a_expr->rexpr, context);
appendStringInfoChar(str, ')');
return;
case AEXPR_OP_ALL:
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, a_expr->name);
appendStringInfoString(str, " ALL(");
deparseExpr(str, a_expr->rexpr, context);
appendStringInfoChar(str, ')');
return;
case AEXPR_DISTINCT:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
if (need_lexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->lexpr, context);
if (need_lexpr_parens)
appendStringInfoChar(str, ')');
appendStringInfoString(str, " IS DISTINCT FROM ");
if (need_rexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->rexpr, context);
if (need_rexpr_parens)
appendStringInfoChar(str, ')');
return;
case AEXPR_NOT_DISTINCT:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoString(str, " IS NOT DISTINCT FROM ");
deparseExpr(str, a_expr->rexpr, context);
return;
case AEXPR_NULLIF:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
appendStringInfoString(str, "NULLIF(");
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoString(str, ", ");
deparseExpr(str, a_expr->rexpr, context);
appendStringInfoChar(str, ')');
return;
case AEXPR_IN:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(IsA(a_expr->rexpr, List));
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
if (strcmp(name, "=") == 0) {
appendStringInfoString(str, "IN ");
} else if (strcmp(name, "<>") == 0) {
appendStringInfoString(str, "NOT IN ");
} else {
Assert(false);
}
appendStringInfoChar(str, '(');
if (IsA(a_expr->rexpr, SubLink))
deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
else
deparseExprList(str, castNode(List, a_expr->rexpr));
appendStringInfoChar(str, ')');
return;
case AEXPR_LIKE:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
if (strcmp(name, "~~") == 0) {
appendStringInfoString(str, "LIKE ");
} else if (strcmp(name, "!~~") == 0) {
appendStringInfoString(str, "NOT LIKE ");
} else {
Assert(false);
}
deparseExpr(str, a_expr->rexpr, context);
return;
case AEXPR_ILIKE:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
if (strcmp(name, "~~*") == 0) {
appendStringInfoString(str, "ILIKE ");
} else if (strcmp(name, "!~~*") == 0) {
appendStringInfoString(str, "NOT ILIKE ");
} else {
Assert(false);
}
deparseExpr(str, a_expr->rexpr, context);
return;
case AEXPR_SIMILAR:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
if (strcmp(name, "~") == 0) {
appendStringInfoString(str, "SIMILAR TO ");
} else if (strcmp(name, "!~") == 0) {
appendStringInfoString(str, "NOT SIMILAR TO ");
} else {
Assert(false);
}
FuncCall *n = castNode(FuncCall, a_expr->rexpr);
Assert(list_length(n->funcname) == 2);
Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
deparseExpr(str, linitial(n->args), context);
if (list_length(n->args) == 2)
{
appendStringInfoString(str, " ESCAPE ");
deparseExpr(str, lsecond(n->args), context);
}
return;
case AEXPR_BETWEEN:
case AEXPR_NOT_BETWEEN:
case AEXPR_BETWEEN_SYM:
case AEXPR_NOT_BETWEEN_SYM:
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(IsA(a_expr->rexpr, List));
deparseExpr(str, a_expr->lexpr, context);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, strVal(linitial(a_expr->name)));
appendStringInfoChar(str, ' ');
foreach(lc, castNode(List, a_expr->rexpr)) {
deparseExpr(str, lfirst(lc), context);
if (lnext(castNode(List, a_expr->rexpr), lc))
appendStringInfoString(str, " AND ");
}
return;
}
}
static void deparseBoolExpr(StringInfo str, BoolExpr *bool_expr)
{
const ListCell *lc = NULL;
switch (bool_expr->boolop)
{
case AND_EXPR:
foreach(lc, bool_expr->args)
{
bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
if (need_parens)
appendStringInfoChar(str, ')');
if (lnext(bool_expr->args, lc))
appendStringInfoString(str, " AND ");
}
return;
case OR_EXPR:
foreach(lc, bool_expr->args)
{
bool need_parens = IsA(lfirst(lc), BoolExpr) && (castNode(BoolExpr, lfirst(lc))->boolop == AND_EXPR || castNode(BoolExpr, lfirst(lc))->boolop == OR_EXPR);
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, lfirst(lc), DEPARSE_NODE_CONTEXT_A_EXPR);
if (need_parens)
appendStringInfoChar(str, ')');
if (lnext(bool_expr->args, lc))
appendStringInfoString(str, " OR ");
}
return;
case NOT_EXPR:
Assert(list_length(bool_expr->args) == 1);
bool need_parens = IsA(linitial(bool_expr->args), BoolExpr) && (castNode(BoolExpr, linitial(bool_expr->args))->boolop == AND_EXPR || castNode(BoolExpr, linitial(bool_expr->args))->boolop == OR_EXPR);
appendStringInfoString(str, "NOT ");
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, linitial(bool_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
if (need_parens)
appendStringInfoChar(str, ')');
return;
}
}
static void deparseAStar(StringInfo str, A_Star *a_star)
{
appendStringInfoChar(str, '*');
}
static void deparseCollateClause(StringInfo str, CollateClause* collate_clause)
{
ListCell *lc;
if (collate_clause->arg != NULL)
{
bool need_parens = IsA(collate_clause->arg, A_Expr);
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, collate_clause->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
if (need_parens)
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "COLLATE ");
deparseAnyName(str, collate_clause->collname);
}
static void deparseSortBy(StringInfo str, SortBy* sort_by)
{
deparseExpr(str, sort_by->node, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
switch (sort_by->sortby_dir)
{
case SORTBY_DEFAULT:
break;
case SORTBY_ASC:
appendStringInfoString(str, "ASC ");
break;
case SORTBY_DESC:
appendStringInfoString(str, "DESC ");
break;
case SORTBY_USING:
appendStringInfoString(str, "USING ");
deparseQualOp(str, sort_by->useOp);
break;
}
switch (sort_by->sortby_nulls)
{
case SORTBY_NULLS_DEFAULT:
break;
case SORTBY_NULLS_FIRST:
appendStringInfoString(str, "NULLS FIRST ");
break;
case SORTBY_NULLS_LAST:
appendStringInfoString(str, "NULLS LAST ");
break;
}
removeTrailingSpace(str);
}
static void deparseParamRef(StringInfo str, ParamRef* param_ref)
{
if (param_ref->number == 0) {
appendStringInfoChar(str, '?');
} else {
appendStringInfo(str, "$%d", param_ref->number);
}
}
static void deparseSQLValueFunction(StringInfo str, SQLValueFunction* sql_value_function)
{
switch (sql_value_function->op)
{
case SVFOP_CURRENT_DATE:
appendStringInfoString(str, "current_date");
break;
case SVFOP_CURRENT_TIME:
appendStringInfoString(str, "current_time");
break;
case SVFOP_CURRENT_TIME_N:
appendStringInfoString(str, "current_time"); break;
case SVFOP_CURRENT_TIMESTAMP:
appendStringInfoString(str, "current_timestamp");
break;
case SVFOP_CURRENT_TIMESTAMP_N:
appendStringInfoString(str, "current_timestamp"); break;
case SVFOP_LOCALTIME:
appendStringInfoString(str, "localtime");
break;
case SVFOP_LOCALTIME_N:
appendStringInfoString(str, "localtime"); break;
case SVFOP_LOCALTIMESTAMP:
appendStringInfoString(str, "localtimestamp");
break;
case SVFOP_LOCALTIMESTAMP_N:
appendStringInfoString(str, "localtimestamp"); break;
case SVFOP_CURRENT_ROLE:
appendStringInfoString(str, "current_role");
break;
case SVFOP_CURRENT_USER:
appendStringInfoString(str, "current_user");
break;
case SVFOP_USER:
appendStringInfoString(str, "user");
break;
case SVFOP_SESSION_USER:
appendStringInfoString(str, "session_user");
break;
case SVFOP_CURRENT_CATALOG:
appendStringInfoString(str, "current_catalog");
break;
case SVFOP_CURRENT_SCHEMA:
appendStringInfoString(str, "current_schema");
break;
}
if (sql_value_function->typmod != -1)
{
appendStringInfo(str, "(%d)", sql_value_function->typmod);
}
}
static void deparseWithClause(StringInfo str, WithClause *with_clause)
{
ListCell *lc;
appendStringInfoString(str, "WITH ");
if (with_clause->recursive)
appendStringInfoString(str, "RECURSIVE ");
foreach(lc, with_clause->ctes) {
deparseCommonTableExpr(str, castNode(CommonTableExpr, lfirst(lc)));
if (lnext(with_clause->ctes, lc))
appendStringInfoString(str, ", ");
}
removeTrailingSpace(str);
}
static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
{
ListCell *lc;
bool need_alias_parens = join_expr->alias != NULL;
bool need_rarg_parens = IsA(join_expr->rarg, JoinExpr) && castNode(JoinExpr, join_expr->rarg)->alias == NULL;
if (need_alias_parens)
appendStringInfoChar(str, '(');
deparseTableRef(str, join_expr->larg);
appendStringInfoChar(str, ' ');
if (join_expr->isNatural)
appendStringInfoString(str, "NATURAL ");
switch (join_expr->jointype)
{
case JOIN_INNER:
if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
appendStringInfoString(str, "CROSS ");
break;
case JOIN_LEFT:
appendStringInfoString(str, "LEFT ");
break;
case JOIN_FULL:
appendStringInfoString(str, "FULL ");
break;
case JOIN_RIGHT:
appendStringInfoString(str, "RIGHT ");
break;
case JOIN_SEMI:
case JOIN_ANTI:
case JOIN_RIGHT_ANTI:
case JOIN_UNIQUE_OUTER:
case JOIN_UNIQUE_INNER:
Assert(false);
break;
}
appendStringInfoString(str, "JOIN ");
if (need_rarg_parens)
appendStringInfoChar(str, '(');
deparseTableRef(str, join_expr->rarg);
if (need_rarg_parens)
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
if (join_expr->quals != NULL)
{
appendStringInfoString(str, "ON ");
deparseExpr(str, join_expr->quals, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
if (list_length(join_expr->usingClause) > 0)
{
appendStringInfoString(str, "USING (");
deparseNameList(str, join_expr->usingClause);
appendStringInfoString(str, ") ");
if (join_expr->join_using_alias)
{
appendStringInfoString(str, "AS ");
appendStringInfoString(str, join_expr->join_using_alias->aliasname);
}
}
if (need_alias_parens)
appendStringInfoString(str, ") ");
if (join_expr->alias != NULL)
deparseAlias(str, join_expr->alias);
removeTrailingSpace(str);
}
static void deparseCTESearchClause(StringInfo str, CTESearchClause *search_clause)
{
appendStringInfoString(str, " SEARCH ");
if (search_clause->search_breadth_first)
appendStringInfoString(str, "BREADTH ");
else
appendStringInfoString(str, "DEPTH ");
appendStringInfoString(str, "FIRST BY ");
if (search_clause->search_col_list)
deparseColumnList(str, search_clause->search_col_list);
appendStringInfoString(str, " SET ");
appendStringInfoString(str, quote_identifier(search_clause->search_seq_column));
}
static void deparseCTECycleClause(StringInfo str, CTECycleClause *cycle_clause)
{
appendStringInfoString(str, " CYCLE ");
if (cycle_clause->cycle_col_list)
deparseColumnList(str, cycle_clause->cycle_col_list);
appendStringInfoString(str, " SET ");
appendStringInfoString(str, quote_identifier(cycle_clause->cycle_mark_column));
if (cycle_clause->cycle_mark_value)
{
appendStringInfoString(str, " TO ");
deparseAexprConst(str, cycle_clause->cycle_mark_value);
}
if (cycle_clause->cycle_mark_default)
{
appendStringInfoString(str, " DEFAULT ");
deparseAexprConst(str, cycle_clause->cycle_mark_default);
}
appendStringInfoString(str, " USING ");
appendStringInfoString(str, quote_identifier(cycle_clause->cycle_path_column));
}
static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
{
deparseColId(str, cte->ctename);
if (list_length(cte->aliascolnames) > 0)
{
appendStringInfoChar(str, '(');
deparseNameList(str, cte->aliascolnames);
appendStringInfoChar(str, ')');
}
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "AS ");
switch (cte->ctematerialized) {
case CTEMaterializeDefault:
break;
case CTEMaterializeAlways:
appendStringInfoString(str, "MATERIALIZED ");
break;
case CTEMaterializeNever:
appendStringInfoString(str, "NOT MATERIALIZED ");
break;
}
appendStringInfoChar(str, '(');
deparsePreparableStmt(str, cte->ctequery);
appendStringInfoChar(str, ')');
if (cte->search_clause)
deparseCTESearchClause(str, cte->search_clause);
if (cte->cycle_clause)
deparseCTECycleClause(str, cte->cycle_clause);
}
static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
{
if (range_subselect->lateral)
appendStringInfoString(str, "LATERAL ");
appendStringInfoChar(str, '(');
deparseSelectStmt(str, castNode(SelectStmt, range_subselect->subquery));
appendStringInfoChar(str, ')');
if (range_subselect->alias != NULL)
{
appendStringInfoChar(str, ' ');
deparseAlias(str, range_subselect->alias);
}
}
static void deparseRangeFunction(StringInfo str, RangeFunction *range_func)
{
ListCell *lc;
ListCell *lc2;
if (range_func->lateral)
appendStringInfoString(str, "LATERAL ");
if (range_func->is_rowsfrom)
{
appendStringInfoString(str, "ROWS FROM ");
appendStringInfoChar(str, '(');
foreach(lc, range_func->functions)
{
List *lfunc = castNode(List, lfirst(lc));
Assert(list_length(lfunc) == 2);
deparseFuncExprWindowless(str, linitial(lfunc));
appendStringInfoChar(str, ' ');
List *coldeflist = castNode(List, lsecond(lfunc));
if (list_length(coldeflist) > 0)
{
appendStringInfoString(str, "AS (");
foreach(lc2, coldeflist)
{
deparseColumnDef(str, castNode(ColumnDef, lfirst(lc2)));
if (lnext(coldeflist, lc2))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
if (lnext(range_func->functions, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
else
{
Assert(list_length(linitial(range_func->functions)) == 2);
deparseFuncExprWindowless(str, linitial(linitial(range_func->functions)));
}
appendStringInfoChar(str, ' ');
if (range_func->ordinality)
appendStringInfoString(str, "WITH ORDINALITY ");
if (range_func->alias != NULL)
{
deparseAlias(str, range_func->alias);
appendStringInfoChar(str, ' ');
}
if (list_length(range_func->coldeflist) > 0)
{
if (range_func->alias == NULL)
appendStringInfoString(str, "AS ");
appendStringInfoChar(str, '(');
foreach(lc, range_func->coldeflist)
{
deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
if (lnext(range_func->coldeflist, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
removeTrailingSpace(str);
}
static void deparseAArrayExpr(StringInfo str, A_ArrayExpr *array_expr)
{
ListCell *lc;
appendStringInfoString(str, "ARRAY[");
deparseExprList(str, array_expr->elements);
appendStringInfoChar(str, ']');
}
static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
{
ListCell *lc;
switch (row_expr->row_format)
{
case COERCE_EXPLICIT_CALL:
appendStringInfoString(str, "ROW");
break;
case COERCE_SQL_SYNTAX:
case COERCE_EXPLICIT_CAST:
Assert(false);
break;
case COERCE_IMPLICIT_CAST:
break;
}
appendStringInfoString(str, "(");
deparseExprList(str, row_expr->args);
appendStringInfoChar(str, ')');
}
static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context)
{
bool need_parens = false;
Assert(type_cast->typeName != NULL);
if (IsA(type_cast->arg, A_Expr) || context == DEPARSE_NODE_CONTEXT_FUNC_EXPR)
{
appendStringInfoString(str, "CAST(");
deparseExpr(str, type_cast->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " AS ");
deparseTypeName(str, type_cast->typeName);
appendStringInfoChar(str, ')');
return;
}
if (IsA(type_cast->arg, A_Const))
{
A_Const *a_const = castNode(A_Const, type_cast->arg);
if (list_length(type_cast->typeName->names) == 2 &&
strcmp(strVal(linitial(type_cast->typeName->names)), "pg_catalog") == 0)
{
char *typename = strVal(lsecond(type_cast->typeName->names));
if (strcmp(typename, "bpchar") == 0 && type_cast->typeName->typmods == NULL)
{
appendStringInfoString(str, "char ");
deparseAConst(str, a_const);
return;
}
else if (strcmp(typename, "bool") == 0 && IsA(&a_const->val, String))
{
char *const_val = strVal(&a_const->val);
if (strcmp(const_val, "t") == 0)
{
appendStringInfoString(str, "true");
return;
}
if (strcmp(const_val, "f") == 0)
{
appendStringInfoString(str, "false");
return;
}
}
else if (strcmp(typename, "interval") == 0 && context == DEPARSE_NODE_CONTEXT_SET_STATEMENT && IsA(&a_const->val, String))
{
appendStringInfoString(str, "interval ");
deparseAConst(str, a_const);
deparseIntervalTypmods(str, type_cast->typeName);
return;
}
}
if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
{
need_parens = true;
}
if (list_length(type_cast->typeName->names) == 1 &&
strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
a_const->location > type_cast->typeName->location)
{
appendStringInfoString(str, " point ");
deparseAConst(str, a_const);
return;
}
}
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, type_cast->arg, DEPARSE_NODE_CONTEXT_NONE );
if (need_parens)
appendStringInfoChar(str, ')');
appendStringInfoString(str, "::");
deparseTypeName(str, type_cast->typeName);
}
static void deparseTypeName(StringInfo str, TypeName *type_name)
{
ListCell *lc;
bool skip_typmods = false;
if (type_name->setof)
appendStringInfoString(str, "SETOF ");
if (list_length(type_name->names) == 2 && strcmp(strVal(linitial(type_name->names)), "pg_catalog") == 0)
{
const char *name = strVal(lsecond(type_name->names));
if (strcmp(name, "bpchar") == 0)
{
appendStringInfoString(str, "char");
}
else if (strcmp(name, "varchar") == 0)
{
appendStringInfoString(str, "varchar");
}
else if (strcmp(name, "numeric") == 0)
{
appendStringInfoString(str, "numeric");
}
else if (strcmp(name, "bool") == 0)
{
appendStringInfoString(str, "boolean");
}
else if (strcmp(name, "int2") == 0)
{
appendStringInfoString(str, "smallint");
}
else if (strcmp(name, "int4") == 0)
{
appendStringInfoString(str, "int");
}
else if (strcmp(name, "int8") == 0)
{
appendStringInfoString(str, "bigint");
}
else if (strcmp(name, "real") == 0 || strcmp(name, "float4") == 0)
{
appendStringInfoString(str, "real");
}
else if (strcmp(name, "float8") == 0)
{
appendStringInfoString(str, "double precision");
}
else if (strcmp(name, "time") == 0)
{
appendStringInfoString(str, "time");
}
else if (strcmp(name, "timetz") == 0)
{
appendStringInfoString(str, "time ");
if (list_length(type_name->typmods) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, type_name->typmods)
{
deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
if (lnext(type_name->typmods, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
appendStringInfoString(str, "with time zone");
skip_typmods = true;
}
else if (strcmp(name, "timestamp") == 0)
{
appendStringInfoString(str, "timestamp");
}
else if (strcmp(name, "timestamptz") == 0)
{
appendStringInfoString(str, "timestamp ");
if (list_length(type_name->typmods) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, type_name->typmods)
{
deparseSignedIconst(str, (Node *) &castNode(A_Const, lfirst(lc))->val);
if (lnext(type_name->typmods, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
appendStringInfoString(str, "with time zone");
skip_typmods = true;
}
else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) == 0)
{
appendStringInfoString(str, "interval");
}
else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
{
appendStringInfoString(str, "interval");
deparseIntervalTypmods(str, type_name);
skip_typmods = true;
}
else
{
appendStringInfoString(str, "pg_catalog.");
appendStringInfoString(str, name);
}
}
else
{
deparseAnyName(str, type_name->names);
}
if (list_length(type_name->typmods) > 0 && !skip_typmods)
{
appendStringInfoChar(str, '(');
foreach(lc, type_name->typmods)
{
if (IsA(lfirst(lc), A_Const))
deparseAConst(str, lfirst(lc));
else if (IsA(lfirst(lc), ParamRef))
deparseParamRef(str, lfirst(lc));
else if (IsA(lfirst(lc), ColumnRef))
deparseColumnRef(str, lfirst(lc));
else
Assert(false);
if (lnext(type_name->typmods, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
foreach(lc, type_name->arrayBounds)
{
appendStringInfoChar(str, '[');
if (IsA(lfirst(lc), Integer) && intVal(lfirst(lc)) != -1)
deparseSignedIconst(str, lfirst(lc));
appendStringInfoChar(str, ']');
}
if (type_name->pct_type)
appendStringInfoString(str, "%type");
}
static void deparseIntervalTypmods(StringInfo str, TypeName *type_name)
{
const char *name = strVal(lsecond(type_name->names));
Assert(strcmp(name, "interval") == 0);
Assert(list_length(type_name->typmods) >= 1);
Assert(IsA(linitial(type_name->typmods), A_Const));
Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
switch (fields)
{
case INTERVAL_MASK(YEAR):
appendStringInfoString(str, " year");
break;
case INTERVAL_MASK(MONTH):
appendStringInfoString(str, " month");
break;
case INTERVAL_MASK(DAY):
appendStringInfoString(str, " day");
break;
case INTERVAL_MASK(HOUR):
appendStringInfoString(str, " hour");
break;
case INTERVAL_MASK(MINUTE):
appendStringInfoString(str, " minute");
break;
case INTERVAL_MASK(SECOND):
appendStringInfoString(str, " second");
break;
case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
appendStringInfoString(str, " year to month");
break;
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
appendStringInfoString(str, " day to hour");
break;
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
appendStringInfoString(str, " day to minute");
break;
case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
appendStringInfoString(str, " day to second");
break;
case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
appendStringInfoString(str, " hour to minute");
break;
case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
appendStringInfoString(str, " hour to second");
break;
case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
appendStringInfoString(str, " minute to second");
break;
case INTERVAL_FULL_RANGE:
break;
default:
Assert(false);
break;
}
if (list_length(type_name->typmods) == 2)
{
int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
if (precision != INTERVAL_FULL_PRECISION)
appendStringInfo(str, "(%d)", precision);
}
}
static void deparseNullTest(StringInfo str, NullTest *null_test)
{
Assert(null_test->argisrow == false);
deparseExpr(str, (Node *) null_test->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
switch (null_test->nulltesttype)
{
case IS_NULL:
appendStringInfoString(str, " IS NULL");
break;
case IS_NOT_NULL:
appendStringInfoString(str, " IS NOT NULL");
break;
}
}
static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr)
{
ListCell *lc;
appendStringInfoString(str, "CASE ");
if (case_expr->arg != NULL)
{
deparseExpr(str, (Node *) case_expr->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
foreach(lc, case_expr->args)
{
deparseCaseWhen(str, castNode(CaseWhen, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
if (case_expr->defresult != NULL)
{
appendStringInfoString(str, "ELSE ");
deparseExpr(str, (Node *) case_expr->defresult, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "END");
}
static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
{
appendStringInfoString(str, "WHEN ");
deparseExpr(str, (Node *) case_when->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " THEN ");
deparseExpr(str, (Node *) case_when->result, DEPARSE_NODE_CONTEXT_A_EXPR);
}
static void deparseAIndirection(StringInfo str, A_Indirection *a_indirection)
{
ListCell *lc;
bool need_parens =
IsA(a_indirection->arg, A_Indirection) ||
IsA(a_indirection->arg, FuncCall) ||
IsA(a_indirection->arg, A_Expr) ||
IsA(a_indirection->arg, TypeCast) ||
IsA(a_indirection->arg, RowExpr) ||
(IsA(a_indirection->arg, ColumnRef) && !IsA(linitial(a_indirection->indirection), A_Indices)) ||
IsA(a_indirection->arg, JsonFuncExpr);
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_indirection->arg, need_parens ? DEPARSE_NODE_CONTEXT_A_EXPR : DEPARSE_NODE_CONTEXT_NONE);
if (need_parens)
appendStringInfoChar(str, ')');
deparseOptIndirection(str, a_indirection->indirection, 0);
}
static void deparseAIndices(StringInfo str, A_Indices *a_indices)
{
appendStringInfoChar(str, '[');
if (a_indices->lidx != NULL)
deparseExpr(str, a_indices->lidx, DEPARSE_NODE_CONTEXT_A_EXPR);
if (a_indices->is_slice)
appendStringInfoChar(str, ':');
if (a_indices->uidx != NULL)
deparseExpr(str, a_indices->uidx, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ']');
}
static void deparseCoalesceExpr(StringInfo str, CoalesceExpr *coalesce_expr)
{
appendStringInfoString(str, "COALESCE(");
deparseExprList(str, coalesce_expr->args);
appendStringInfoChar(str, ')');
}
static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr)
{
switch (min_max_expr->op)
{
case IS_GREATEST:
appendStringInfoString(str, "GREATEST(");
break;
case IS_LEAST:
appendStringInfoString(str, "LEAST(");
break;
}
deparseExprList(str, min_max_expr->args);
appendStringInfoChar(str, ')');
}
static void deparseBooleanTest(StringInfo str, BooleanTest *boolean_test)
{
bool need_parens = IsA(boolean_test->arg, BoolExpr);
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, (Node *) boolean_test->arg, DEPARSE_NODE_CONTEXT_A_EXPR);
if (need_parens)
appendStringInfoChar(str, ')');
switch (boolean_test->booltesttype)
{
case IS_TRUE:
appendStringInfoString(str, " IS TRUE");
break;
case IS_NOT_TRUE:
appendStringInfoString(str, " IS NOT TRUE");
break;
case IS_FALSE:
appendStringInfoString(str, " IS FALSE");
break;
case IS_NOT_FALSE:
appendStringInfoString(str, " IS NOT FALSE");
break;
case IS_UNKNOWN:
appendStringInfoString(str, " IS UNKNOWN");
break;
case IS_NOT_UNKNOWN:
appendStringInfoString(str, " IS NOT UNKNOWN");
break;
default:
Assert(false);
}
}
static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
{
ListCell *lc;
if (column_def->colname != NULL)
{
appendStringInfoString(str, quote_identifier(column_def->colname));
appendStringInfoChar(str, ' ');
}
if (column_def->typeName != NULL)
{
deparseTypeName(str, column_def->typeName);
appendStringInfoChar(str, ' ');
}
if (column_def->storage_name)
{
appendStringInfoString(str, "STORAGE ");
appendStringInfoString(str, column_def->storage_name);
appendStringInfoChar(str, ' ');
}
if (column_def->raw_default != NULL)
{
appendStringInfoString(str, "USING ");
deparseExpr(str, column_def->raw_default, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
if (column_def->compression != NULL)
{
appendStringInfoString(str, "COMPRESSION ");
appendStringInfoString(str, column_def->compression);
appendStringInfoChar(str, ' ');
}
if (column_def->fdwoptions != NULL)
{
deparseCreateGenericOptions(str, column_def->fdwoptions);
appendStringInfoChar(str, ' ');
}
foreach(lc, column_def->constraints)
{
deparseConstraint(str, castNode(Constraint, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
if (column_def->collClause != NULL)
{
deparseCollateClause(str, column_def->collClause);
}
removeTrailingSpace(str);
}
static void deparseInsertOverride(StringInfo str, OverridingKind override)
{
switch (override)
{
case OVERRIDING_NOT_SET:
break;
case OVERRIDING_USER_VALUE:
appendStringInfoString(str, "OVERRIDING USER VALUE ");
break;
case OVERRIDING_SYSTEM_VALUE:
appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
break;
}
}
static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
{
ListCell *lc;
ListCell *lc2;
if (insert_stmt->withClause != NULL)
{
deparseWithClause(str, insert_stmt->withClause);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "INSERT INTO ");
deparseRangeVar(str, insert_stmt->relation, DEPARSE_NODE_CONTEXT_INSERT_RELATION);
appendStringInfoChar(str, ' ');
if (list_length(insert_stmt->cols) > 0)
{
appendStringInfoChar(str, '(');
deparseInsertColumnList(str, insert_stmt->cols);
appendStringInfoString(str, ") ");
}
deparseInsertOverride(str, insert_stmt->override);
if (insert_stmt->selectStmt != NULL)
{
deparseSelectStmt(str, castNode(SelectStmt, insert_stmt->selectStmt));
appendStringInfoChar(str, ' ');
}
else
{
appendStringInfoString(str, "DEFAULT VALUES ");
}
if (insert_stmt->onConflictClause != NULL)
{
deparseOnConflictClause(str, insert_stmt->onConflictClause);
appendStringInfoChar(str, ' ');
}
if (list_length(insert_stmt->returningList) > 0)
{
appendStringInfoString(str, "RETURNING ");
deparseTargetList(str, insert_stmt->returningList);
}
removeTrailingSpace(str);
}
static void deparseInferClause(StringInfo str, InferClause *infer_clause)
{
ListCell *lc;
if (list_length(infer_clause->indexElems) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, infer_clause->indexElems)
{
deparseIndexElem(str, lfirst(lc));
if (lnext(infer_clause->indexElems, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
if (infer_clause->conname != NULL)
{
appendStringInfoString(str, "ON CONSTRAINT ");
appendStringInfoString(str, quote_identifier(infer_clause->conname));
appendStringInfoChar(str, ' ');
}
deparseWhereClause(str, infer_clause->whereClause);
removeTrailingSpace(str);
}
static void deparseOnConflictClause(StringInfo str, OnConflictClause *on_conflict_clause)
{
ListCell *lc;
appendStringInfoString(str, "ON CONFLICT ");
if (on_conflict_clause->infer != NULL)
{
deparseInferClause(str, on_conflict_clause->infer);
appendStringInfoChar(str, ' ');
}
switch (on_conflict_clause->action)
{
case ONCONFLICT_NONE:
Assert(false);
break;
case ONCONFLICT_NOTHING:
appendStringInfoString(str, "DO NOTHING ");
break;
case ONCONFLICT_UPDATE:
appendStringInfoString(str, "DO UPDATE ");
break;
}
if (list_length(on_conflict_clause->targetList) > 0)
{
appendStringInfoString(str, "SET ");
deparseSetClauseList(str, on_conflict_clause->targetList);
appendStringInfoChar(str, ' ');
}
deparseWhereClause(str, on_conflict_clause->whereClause);
removeTrailingSpace(str);
}
static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
{
ListCell* lc;
ListCell* lc2;
ListCell* lc3;
if (update_stmt->withClause != NULL)
{
deparseWithClause(str, update_stmt->withClause);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "UPDATE ");
deparseRangeVar(str, update_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (list_length(update_stmt->targetList) > 0)
{
appendStringInfoString(str, "SET ");
deparseSetClauseList(str, update_stmt->targetList);
appendStringInfoChar(str, ' ');
}
deparseFromClause(str, update_stmt->fromClause);
deparseWhereOrCurrentClause(str, update_stmt->whereClause);
if (list_length(update_stmt->returningList) > 0)
{
appendStringInfoString(str, "RETURNING ");
deparseTargetList(str, update_stmt->returningList);
}
removeTrailingSpace(str);
}
static void deparseMergeStmt(StringInfo str, MergeStmt *merge_stmt)
{
if (merge_stmt->withClause != NULL)
{
deparseWithClause(str, merge_stmt->withClause);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "MERGE INTO ");
deparseRangeVar(str, merge_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "USING ");
deparseTableRef(str, merge_stmt->sourceRelation);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "ON ");
deparseExpr(str, merge_stmt->joinCondition, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
ListCell *lc;
foreach (lc, merge_stmt->mergeWhenClauses)
{
MergeWhenClause *clause = castNode(MergeWhenClause, lfirst(lc));
appendStringInfoString(str, "WHEN ");
switch (clause->matchKind)
{
case MERGE_WHEN_MATCHED:
appendStringInfoString(str, "MATCHED ");
break;
case MERGE_WHEN_NOT_MATCHED_BY_SOURCE:
appendStringInfoString(str, "NOT MATCHED BY SOURCE ");
break;
case MERGE_WHEN_NOT_MATCHED_BY_TARGET:
appendStringInfoString(str, "NOT MATCHED ");
break;
}
if (clause->condition)
{
appendStringInfoString(str, "AND ");
deparseExpr(str, clause->condition, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "THEN ");
switch (clause->commandType) {
case CMD_INSERT:
appendStringInfoString(str, "INSERT ");
if (clause->targetList) {
appendStringInfoChar(str, '(');
deparseInsertColumnList(str, clause->targetList);
appendStringInfoString(str, ") ");
}
deparseInsertOverride(str, clause->override);
if (clause->values) {
appendStringInfoString(str, "VALUES (");
deparseExprList(str, clause->values);
appendStringInfoString(str, ")");
} else {
appendStringInfoString(str, "DEFAULT VALUES ");
}
break;
case CMD_UPDATE:
appendStringInfoString(str, "UPDATE SET ");
deparseSetClauseList(str, clause->targetList);
break;
case CMD_DELETE:
appendStringInfoString(str, "DELETE");
break;
case CMD_NOTHING:
appendStringInfoString(str, "DO NOTHING");
break;
default:
elog(ERROR, "deparse: unpermitted command type in merge statement: %d", clause->commandType);
break;
}
if (lfirst(lc) != llast(merge_stmt->mergeWhenClauses))
appendStringInfoChar(str, ' ');
}
if (merge_stmt->returningList)
{
appendStringInfoString(str, " RETURNING ");
deparseTargetList(str, merge_stmt->returningList);
}
}
static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
{
if (delete_stmt->withClause != NULL)
{
deparseWithClause(str, delete_stmt->withClause);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "DELETE FROM ");
deparseRangeVar(str, delete_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (delete_stmt->usingClause != NULL)
{
appendStringInfoString(str, "USING ");
deparseFromList(str, delete_stmt->usingClause);
appendStringInfoChar(str, ' ');
}
deparseWhereOrCurrentClause(str, delete_stmt->whereClause);
if (list_length(delete_stmt->returningList) > 0)
{
appendStringInfoString(str, "RETURNING ");
deparseTargetList(str, delete_stmt->returningList);
}
removeTrailingSpace(str);
}
static void deparseLockingClause(StringInfo str, LockingClause *locking_clause)
{
ListCell *lc;
switch (locking_clause->strength)
{
case LCS_NONE:
Assert(false);
break;
case LCS_FORKEYSHARE:
appendStringInfoString(str, "FOR KEY SHARE ");
break;
case LCS_FORSHARE:
appendStringInfoString(str, "FOR SHARE ");
break;
case LCS_FORNOKEYUPDATE:
appendStringInfoString(str, "FOR NO KEY UPDATE ");
break;
case LCS_FORUPDATE:
appendStringInfoString(str, "FOR UPDATE ");
break;
}
if (list_length(locking_clause->lockedRels) > 0)
{
appendStringInfoString(str, "OF ");
deparseQualifiedNameList(str, locking_clause->lockedRels);
}
switch (locking_clause->waitPolicy)
{
case LockWaitError:
appendStringInfoString(str, "NOWAIT");
break;
case LockWaitSkip:
appendStringInfoString(str, "SKIP LOCKED");
break;
case LockWaitBlock:
break;
}
removeTrailingSpace(str);
}
static void deparseSetToDefault(StringInfo str, SetToDefault *set_to_default)
{
appendStringInfoString(str, "DEFAULT");
}
static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_stmt)
{
ListCell *lc;
ListCell *lc2;
appendStringInfoString(str, "CREATE CAST (");
deparseTypeName(str, create_cast_stmt->sourcetype);
appendStringInfoString(str, " AS ");
deparseTypeName(str, create_cast_stmt->targettype);
appendStringInfoString(str, ") ");
if (create_cast_stmt->func != NULL)
{
appendStringInfoString(str, "WITH FUNCTION ");
deparseFunctionWithArgtypes(str, create_cast_stmt->func);
appendStringInfoChar(str, ' ');
}
else if (create_cast_stmt->inout)
{
appendStringInfoString(str, "WITH INOUT ");
}
else
{
appendStringInfoString(str, "WITHOUT FUNCTION ");
}
switch (create_cast_stmt->context)
{
case COERCION_IMPLICIT:
appendStringInfoString(str, "AS IMPLICIT");
break;
case COERCION_ASSIGNMENT:
appendStringInfoString(str, "AS ASSIGNMENT");
break;
case COERCION_PLPGSQL:
Assert(false);
break;
case COERCION_EXPLICIT:
break;
}
}
static void deparseCreateOpClassStmt(StringInfo str, CreateOpClassStmt *create_op_class_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "CREATE OPERATOR CLASS ");
deparseAnyName(str, create_op_class_stmt->opclassname);
appendStringInfoChar(str, ' ');
if (create_op_class_stmt->isDefault)
appendStringInfoString(str, "DEFAULT ");
appendStringInfoString(str, "FOR TYPE ");
deparseTypeName(str, create_op_class_stmt->datatype);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(create_op_class_stmt->amname));
appendStringInfoChar(str, ' ');
if (create_op_class_stmt->opfamilyname != NULL)
{
appendStringInfoString(str, "FAMILY ");
deparseAnyName(str, create_op_class_stmt->opfamilyname);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "AS ");
deparseOpclassItemList(str, create_op_class_stmt->items);
}
static void deparseCreateOpFamilyStmt(StringInfo str, CreateOpFamilyStmt *create_op_family_stmt)
{
appendStringInfoString(str, "CREATE OPERATOR FAMILY ");
deparseAnyName(str, create_op_family_stmt->opfamilyname);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(create_op_family_stmt->amname));
}
static void deparseCreateOpClassItem(StringInfo str, CreateOpClassItem *create_op_class_item)
{
ListCell *lc = NULL;
switch (create_op_class_item->itemtype)
{
case OPCLASS_ITEM_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
appendStringInfo(str, "%d ", create_op_class_item->number);
if (create_op_class_item->name != NULL)
{
if (create_op_class_item->name->objargs != NULL)
deparseOperatorWithArgtypes(str, create_op_class_item->name);
else
deparseAnyOperator(str, create_op_class_item->name->objname);
appendStringInfoChar(str, ' ');
}
if (create_op_class_item->order_family != NULL)
{
appendStringInfoString(str, "FOR ORDER BY ");
deparseAnyName(str, create_op_class_item->order_family);
}
if (create_op_class_item->class_args != NULL)
{
appendStringInfoChar(str, '(');
deparseTypeList(str, create_op_class_item->class_args);
appendStringInfoChar(str, ')');
}
removeTrailingSpace(str);
break;
case OPCLASS_ITEM_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
appendStringInfo(str, "%d ", create_op_class_item->number);
if (create_op_class_item->class_args != NULL)
{
appendStringInfoChar(str, '(');
deparseTypeList(str, create_op_class_item->class_args);
appendStringInfoString(str, ") ");
}
if (create_op_class_item->name != NULL)
deparseFunctionWithArgtypes(str, create_op_class_item->name);
removeTrailingSpace(str);
break;
case OPCLASS_ITEM_STORAGETYPE:
appendStringInfoString(str, "STORAGE ");
deparseTypeName(str, create_op_class_item->storedtype);
break;
default:
Assert(false);
}
}
static void deparseTableLikeClause(StringInfo str, TableLikeClause *table_like_clause)
{
appendStringInfoString(str, "LIKE ");
deparseRangeVar(str, table_like_clause->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (table_like_clause->options == CREATE_TABLE_LIKE_ALL)
appendStringInfoString(str, "INCLUDING ALL ");
else
{
if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
appendStringInfoString(str, "INCLUDING COMMENTS ");
if (table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION)
appendStringInfoString(str, "INCLUDING COMPRESSION ");
if (table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS)
appendStringInfoString(str, "INCLUDING CONSTRAINTS ");
if (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)
appendStringInfoString(str, "INCLUDING DEFAULTS ");
if (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)
appendStringInfoString(str, "INCLUDING IDENTITY ");
if (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED)
appendStringInfoString(str, "INCLUDING GENERATED ");
if (table_like_clause->options & CREATE_TABLE_LIKE_INDEXES)
appendStringInfoString(str, "INCLUDING INDEXES ");
if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
appendStringInfoString(str, "INCLUDING STATISTICS ");
if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
appendStringInfoString(str, "INCLUDING STORAGE ");
}
removeTrailingSpace(str);
}
static void deparseCreateDomainStmt(StringInfo str, CreateDomainStmt *create_domain_stmt)
{
ListCell *lc;
Assert(create_domain_stmt->typeName != NULL);
appendStringInfoString(str, "CREATE DOMAIN ");
deparseAnyName(str, create_domain_stmt->domainname);
appendStringInfoString(str, " AS ");
deparseTypeName(str, create_domain_stmt->typeName);
appendStringInfoChar(str, ' ');
if (create_domain_stmt->collClause != NULL)
{
deparseCollateClause(str, create_domain_stmt->collClause);
appendStringInfoChar(str, ' ');
}
foreach(lc, create_domain_stmt->constraints)
{
deparseConstraint(str, castNode(Constraint, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseCreateExtensionStmt(StringInfo str, CreateExtensionStmt *create_extension_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "CREATE EXTENSION ");
if (create_extension_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
deparseColId(str, create_extension_stmt->extname);
appendStringInfoChar(str, ' ');
foreach (lc, create_extension_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "schema") == 0)
{
appendStringInfoString(str, "SCHEMA ");
deparseColId(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "new_version") == 0)
{
appendStringInfoString(str, "VERSION ");
deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "cascade") == 0)
{
appendStringInfoString(str, "CASCADE");
}
else
{
Assert(false);
}
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseConstraint(StringInfo str, Constraint *constraint)
{
ListCell *lc;
if (constraint->conname != NULL)
{
appendStringInfoString(str, "CONSTRAINT ");
appendStringInfoString(str, quote_identifier(constraint->conname));
appendStringInfoChar(str, ' ');
}
switch (constraint->contype) {
case CONSTR_NULL:
appendStringInfoString(str, "NULL ");
break;
case CONSTR_NOTNULL:
appendStringInfoString(str, "NOT NULL ");
break;
case CONSTR_DEFAULT:
appendStringInfoString(str, "DEFAULT ");
deparseBExpr(str, constraint->raw_expr);
break;
case CONSTR_IDENTITY:
appendStringInfoString(str, "GENERATED ");
switch (constraint->generated_when)
{
case ATTRIBUTE_IDENTITY_ALWAYS:
appendStringInfoString(str, "ALWAYS ");
break;
case ATTRIBUTE_IDENTITY_BY_DEFAULT:
appendStringInfoString(str, "BY DEFAULT ");
break;
default:
Assert(false);
}
appendStringInfoString(str, "AS IDENTITY ");
deparseOptParenthesizedSeqOptList(str, constraint->options);
break;
case CONSTR_GENERATED:
Assert(constraint->generated_when == ATTRIBUTE_IDENTITY_ALWAYS);
appendStringInfoString(str, "GENERATED ALWAYS AS (");
deparseExpr(str, constraint->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") STORED ");
break;
case CONSTR_CHECK:
appendStringInfoString(str, "CHECK (");
deparseExpr(str, constraint->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
break;
case CONSTR_PRIMARY:
appendStringInfoString(str, "PRIMARY KEY ");
break;
case CONSTR_UNIQUE:
appendStringInfoString(str, "UNIQUE ");
if (constraint->nulls_not_distinct)
appendStringInfoString(str, "NULLS NOT DISTINCT ");
break;
case CONSTR_EXCLUSION:
appendStringInfoString(str, "EXCLUDE ");
if (strcmp(constraint->access_method, DEFAULT_INDEX_TYPE) != 0)
{
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(constraint->access_method));
appendStringInfoChar(str, ' ');
}
appendStringInfoChar(str, '(');
foreach(lc, constraint->exclusions)
{
List *exclusion = castNode(List, lfirst(lc));
Assert(list_length(exclusion) == 2);
deparseIndexElem(str, castNode(IndexElem, linitial(exclusion)));
appendStringInfoString(str, " WITH ");
deparseAnyOperator(str, castNode(List, lsecond(exclusion)));
if (lnext(constraint->exclusions, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
if (constraint->where_clause != NULL)
{
appendStringInfoString(str, "WHERE (");
deparseExpr(str, constraint->where_clause, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
break;
case CONSTR_FOREIGN:
if (list_length(constraint->fk_attrs) > 0)
appendStringInfoString(str, "FOREIGN KEY ");
break;
case CONSTR_ATTR_DEFERRABLE:
appendStringInfoString(str, "DEFERRABLE ");
break;
case CONSTR_ATTR_NOT_DEFERRABLE:
appendStringInfoString(str, "NOT DEFERRABLE ");
break;
case CONSTR_ATTR_DEFERRED:
appendStringInfoString(str, "INITIALLY DEFERRED ");
break;
case CONSTR_ATTR_IMMEDIATE:
appendStringInfoString(str, "INITIALLY IMMEDIATE ");
break;
}
if (list_length(constraint->keys) > 0)
{
bool valueOnly = false;
if (list_length(constraint->keys) == 1) {
Node* firstKey = constraint->keys->elements[0].ptr_value;
valueOnly = IsA(firstKey, String) && !strcmp("value", ((String*)firstKey)->sval);
}
if (!valueOnly) {
appendStringInfoChar(str, '(');
deparseColumnList(str, constraint->keys);
appendStringInfoString(str, ") ");
}
}
if (list_length(constraint->fk_attrs) > 0)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, constraint->fk_attrs);
appendStringInfoString(str, ") ");
}
if (constraint->pktable != NULL)
{
appendStringInfoString(str, "REFERENCES ");
deparseRangeVar(str, constraint->pktable, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (list_length(constraint->pk_attrs) > 0)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, constraint->pk_attrs);
appendStringInfoString(str, ") ");
}
}
switch (constraint->fk_matchtype)
{
case FKCONSTR_MATCH_SIMPLE:
break;
case FKCONSTR_MATCH_FULL:
appendStringInfoString(str, "MATCH FULL ");
break;
case FKCONSTR_MATCH_PARTIAL:
Assert(false);
break;
default:
break;
}
switch (constraint->fk_upd_action)
{
case FKCONSTR_ACTION_NOACTION:
break;
case FKCONSTR_ACTION_RESTRICT:
appendStringInfoString(str, "ON UPDATE RESTRICT ");
break;
case FKCONSTR_ACTION_CASCADE:
appendStringInfoString(str, "ON UPDATE CASCADE ");
break;
case FKCONSTR_ACTION_SETNULL:
appendStringInfoString(str, "ON UPDATE SET NULL ");
break;
case FKCONSTR_ACTION_SETDEFAULT:
appendStringInfoString(str, "ON UPDATE SET DEFAULT ");
break;
default:
break;
}
switch (constraint->fk_del_action)
{
case FKCONSTR_ACTION_NOACTION:
break;
case FKCONSTR_ACTION_RESTRICT:
appendStringInfoString(str, "ON DELETE RESTRICT ");
break;
case FKCONSTR_ACTION_CASCADE:
appendStringInfoString(str, "ON DELETE CASCADE ");
break;
case FKCONSTR_ACTION_SETNULL:
case FKCONSTR_ACTION_SETDEFAULT:
appendStringInfoString(str, "ON DELETE SET ");
switch (constraint->fk_del_action) {
case FKCONSTR_ACTION_SETDEFAULT: appendStringInfoString(str, "DEFAULT "); break;
case FKCONSTR_ACTION_SETNULL: appendStringInfoString(str, "NULL "); break;
}
if (constraint->fk_del_set_cols) {
appendStringInfoString(str, "(");
ListCell *lc;
foreach (lc, constraint->fk_del_set_cols) {
appendStringInfoString(str, strVal(lfirst(lc)));
if (lfirst(lc) != llast(constraint->fk_del_set_cols))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ")");
}
break;
default:
break;
}
if (list_length(constraint->including) > 0)
{
appendStringInfoString(str, "INCLUDE (");
deparseColumnList(str, constraint->including);
appendStringInfoString(str, ") ");
}
switch (constraint->contype)
{
case CONSTR_PRIMARY:
case CONSTR_UNIQUE:
case CONSTR_EXCLUSION:
deparseOptWith(str, constraint->options);
break;
default:
break;
}
if (constraint->indexname != NULL)
appendStringInfo(str, "USING INDEX %s ", quote_identifier(constraint->indexname));
if (constraint->indexspace != NULL)
appendStringInfo(str, "USING INDEX TABLESPACE %s ", quote_identifier(constraint->indexspace));
if (constraint->deferrable)
appendStringInfoString(str, "DEFERRABLE ");
if (constraint->initdeferred)
appendStringInfoString(str, "INITIALLY DEFERRED ");
if (constraint->is_no_inherit)
appendStringInfoString(str, "NO INHERIT ");
if (constraint->skip_validation)
appendStringInfoString(str, "NOT VALID ");
removeTrailingSpace(str);
}
static void deparseReturnStmt(StringInfo str, ReturnStmt *return_stmt)
{
appendStringInfoString(str, "RETURN ");
deparseExpr(str, return_stmt->returnval, DEPARSE_NODE_CONTEXT_A_EXPR);
}
static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
{
ListCell *lc;
bool tableFunc = false;
appendStringInfoString(str, "CREATE ");
if (create_function_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
if (create_function_stmt->is_procedure)
appendStringInfoString(str, "PROCEDURE ");
else
appendStringInfoString(str, "FUNCTION ");
deparseFuncName(str, create_function_stmt->funcname);
appendStringInfoChar(str, '(');
foreach(lc, create_function_stmt->parameters)
{
FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
if (function_parameter->mode != FUNC_PARAM_TABLE)
{
deparseFunctionParameter(str, function_parameter);
if (lnext(create_function_stmt->parameters, lc) && castNode(FunctionParameter, lfirst(lnext(create_function_stmt->parameters, lc)))->mode != FUNC_PARAM_TABLE)
appendStringInfoString(str, ", ");
}
else
{
tableFunc = true;
}
}
appendStringInfoString(str, ") ");
if (tableFunc)
{
appendStringInfoString(str, "RETURNS TABLE (");
foreach(lc, create_function_stmt->parameters)
{
FunctionParameter *function_parameter = castNode(FunctionParameter, lfirst(lc));
if (function_parameter->mode == FUNC_PARAM_TABLE)
{
deparseFunctionParameter(str, function_parameter);
if (lnext(create_function_stmt->parameters, lc))
appendStringInfoString(str, ", ");
}
}
appendStringInfoString(str, ") ");
}
else if (create_function_stmt->returnType != NULL)
{
appendStringInfoString(str, "RETURNS ");
deparseTypeName(str, create_function_stmt->returnType);
appendStringInfoChar(str, ' ');
}
foreach(lc, create_function_stmt->options)
{
deparseCreateFuncOptItem(str, castNode(DefElem, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
if (create_function_stmt->sql_body)
{
if (IsA(create_function_stmt->sql_body, ReturnStmt))
{
deparseReturnStmt(str, castNode(ReturnStmt, create_function_stmt->sql_body));
}
else
{
appendStringInfoString(str, "BEGIN ATOMIC ");
if (IsA(create_function_stmt->sql_body, List), linitial((List *) create_function_stmt->sql_body) != NULL)
{
List *body_stmt_list = castNode(List, linitial((List *) create_function_stmt->sql_body));
foreach(lc, body_stmt_list)
{
if (IsA(lfirst(lc), ReturnStmt))
{
deparseReturnStmt(str, lfirst_node(ReturnStmt, lc));
appendStringInfoString(str, "; ");
}
else
{
deparseStmt(str, lfirst(lc));
appendStringInfoString(str, "; ");
}
}
}
appendStringInfoString(str, "END ");
}
}
removeTrailingSpace(str);
}
static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
{
switch (function_parameter->mode)
{
case FUNC_PARAM_IN:
appendStringInfoString(str, "IN ");
break;
case FUNC_PARAM_OUT:
appendStringInfoString(str, "OUT ");
break;
case FUNC_PARAM_INOUT:
appendStringInfoString(str, "INOUT ");
break;
case FUNC_PARAM_VARIADIC:
appendStringInfoString(str, "VARIADIC ");
break;
case FUNC_PARAM_TABLE:
break;
case FUNC_PARAM_DEFAULT:
break;
default:
Assert(false);
break;
}
if (function_parameter->name != NULL)
{
appendStringInfoString(str, function_parameter->name);
appendStringInfoChar(str, ' ');
}
deparseTypeName(str, function_parameter->argType);
appendStringInfoChar(str, ' ');
if (function_parameter->defexpr != NULL)
{
appendStringInfoString(str, "= ");
deparseExpr(str, function_parameter->defexpr, DEPARSE_NODE_CONTEXT_A_EXPR);
}
removeTrailingSpace(str);
}
static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_stmt)
{
appendStringInfoString(str, "CHECKPOINT");
}
static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE SCHEMA ");
if (create_schema_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
if (create_schema_stmt->schemaname)
{
deparseColId(str, create_schema_stmt->schemaname);
appendStringInfoChar(str, ' ');
}
if (create_schema_stmt->authrole != NULL)
{
appendStringInfoString(str, "AUTHORIZATION ");
deparseRoleSpec(str, create_schema_stmt->authrole);
appendStringInfoChar(str, ' ');
}
if (create_schema_stmt->schemaElts)
{
foreach(lc, create_schema_stmt->schemaElts)
{
deparseSchemaStmt(str, lfirst(lc));
if (lnext(create_schema_stmt->schemaElts, lc))
appendStringInfoChar(str, ' ');
}
}
removeTrailingSpace(str);
}
static void deparseAlterRoleSetStmt(StringInfo str, AlterRoleSetStmt *alter_role_set_stmt)
{
appendStringInfoString(str, "ALTER ROLE ");
if (alter_role_set_stmt->role == NULL)
appendStringInfoString(str, "ALL");
else
deparseRoleSpec(str, alter_role_set_stmt->role);
appendStringInfoChar(str, ' ');
if (alter_role_set_stmt->database != NULL)
{
appendStringInfoString(str, "IN DATABASE ");
appendStringInfoString(str, quote_identifier(alter_role_set_stmt->database));
appendStringInfoChar(str, ' ');
}
deparseVariableSetStmt(str, alter_role_set_stmt->setstmt);
}
static void deparseCreateConversionStmt(StringInfo str, CreateConversionStmt *create_conversion_stmt)
{
appendStringInfoString(str, "CREATE ");
if (create_conversion_stmt->def)
appendStringInfoString(str, "DEFAULT ");
appendStringInfoString(str, "CONVERSION ");
deparseAnyName(str, create_conversion_stmt->conversion_name);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "FOR ");
deparseStringLiteral(str, create_conversion_stmt->for_encoding_name);
appendStringInfoString(str, " TO ");
deparseStringLiteral(str, create_conversion_stmt->to_encoding_name);
appendStringInfoString(str, "FROM ");
deparseAnyName(str, create_conversion_stmt->func_name);
}
static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
{
switch (role_spec->roletype)
{
case ROLESPEC_CSTRING:
Assert(role_spec->rolename != NULL);
appendStringInfoString(str, quote_identifier(role_spec->rolename));
break;
case ROLESPEC_CURRENT_ROLE:
appendStringInfoString(str, "CURRENT_ROLE");
break;
case ROLESPEC_CURRENT_USER:
appendStringInfoString(str, "CURRENT_USER");
break;
case ROLESPEC_SESSION_USER:
appendStringInfoString(str, "SESSION_USER");
break;
case ROLESPEC_PUBLIC:
appendStringInfoString(str, "public");
break;
}
}
static void deparsePartitionElem(StringInfo str, PartitionElem *partition_elem)
{
ListCell *lc;
if (partition_elem->name != NULL)
{
deparseColId(str, partition_elem->name);
appendStringInfoChar(str, ' ');
}
else if (partition_elem->expr != NULL)
{
appendStringInfoChar(str, '(');
deparseExpr(str, partition_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
deparseOptCollate(str, partition_elem->collation);
deparseAnyName(str, partition_elem->opclass);
removeTrailingSpace(str);
}
static void deparsePartitionSpec(StringInfo str, PartitionSpec *partition_spec)
{
ListCell *lc;
appendStringInfoString(str, "PARTITION BY ");
switch (partition_spec->strategy)
{
case PARTITION_STRATEGY_LIST:
appendStringInfoString(str, "LIST");
break;
case PARTITION_STRATEGY_HASH:
appendStringInfoString(str, "HASH");
break;
case PARTITION_STRATEGY_RANGE:
appendStringInfoString(str, "RANGE");
break;
}
appendStringInfoChar(str, '(');
foreach(lc, partition_spec->partParams)
{
deparsePartitionElem(str, castNode(PartitionElem, lfirst(lc)));
if (lnext(partition_spec->partParams, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparsePartitionBoundSpec(StringInfo str, PartitionBoundSpec *partition_bound_spec)
{
ListCell *lc;
if (partition_bound_spec->is_default)
{
appendStringInfoString(str, "DEFAULT");
return;
}
appendStringInfoString(str, "FOR VALUES ");
switch (partition_bound_spec->strategy)
{
case PARTITION_STRATEGY_HASH:
appendStringInfo(str, "WITH (MODULUS %d, REMAINDER %d)", partition_bound_spec->modulus, partition_bound_spec->remainder);
break;
case PARTITION_STRATEGY_LIST:
appendStringInfoString(str, "IN (");
deparseExprList(str, partition_bound_spec->listdatums);
appendStringInfoChar(str, ')');
break;
case PARTITION_STRATEGY_RANGE:
appendStringInfoString(str, "FROM (");
deparseExprList(str, partition_bound_spec->lowerdatums);
appendStringInfoString(str, ") TO (");
deparseExprList(str, partition_bound_spec->upperdatums);
appendStringInfoChar(str, ')');
break;
default:
Assert(false);
break;
}
}
static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
{
deparseRangeVar(str, partition_cmd->name, DEPARSE_NODE_CONTEXT_NONE);
if (partition_cmd->bound != NULL)
{
appendStringInfoChar(str, ' ');
deparsePartitionBoundSpec(str, partition_cmd->bound);
}
if (partition_cmd->concurrent)
appendStringInfoString(str, " CONCURRENTLY ");
}
static void deparseTableElement(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_ColumnDef:
deparseColumnDef(str, castNode(ColumnDef, node));
break;
case T_TableLikeClause:
deparseTableLikeClause(str, castNode(TableLikeClause, node));
break;
case T_Constraint:
deparseConstraint(str, castNode(Constraint, node));
break;
default:
Assert(false);
}
}
static void deparseCreateStmt(StringInfo str, CreateStmt *create_stmt, bool is_foreign_table)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
if (is_foreign_table)
appendStringInfoString(str, "FOREIGN ");
deparseOptTemp(str, create_stmt->relation->relpersistence);
appendStringInfoString(str, "TABLE ");
if (create_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
deparseRangeVar(str, create_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (create_stmt->ofTypename != NULL)
{
appendStringInfoString(str, "OF ");
deparseTypeName(str, create_stmt->ofTypename);
appendStringInfoChar(str, ' ');
}
if (create_stmt->partbound != NULL)
{
Assert(list_length(create_stmt->inhRelations) == 1);
appendStringInfoString(str, "PARTITION OF ");
deparseRangeVar(str, castNode(RangeVar, linitial(create_stmt->inhRelations)), DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
}
if (list_length(create_stmt->tableElts) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, create_stmt->tableElts)
{
deparseTableElement(str, lfirst(lc));
if (lnext(create_stmt->tableElts, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
else if (create_stmt->partbound == NULL && create_stmt->ofTypename == NULL)
{
appendStringInfoString(str, "() ");
}
if (create_stmt->partbound != NULL)
{
deparsePartitionBoundSpec(str, create_stmt->partbound);
appendStringInfoChar(str, ' ');
}
else
{
deparseOptInherit(str, create_stmt->inhRelations);
}
if (create_stmt->partspec != NULL)
{
deparsePartitionSpec(str, create_stmt->partspec);
appendStringInfoChar(str, ' ');
}
if (create_stmt->accessMethod != NULL)
{
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(create_stmt->accessMethod));
}
deparseOptWith(str, create_stmt->options);
switch (create_stmt->oncommit)
{
case ONCOMMIT_NOOP:
break;
case ONCOMMIT_PRESERVE_ROWS:
appendStringInfoString(str, "ON COMMIT PRESERVE ROWS ");
break;
case ONCOMMIT_DELETE_ROWS:
appendStringInfoString(str, "ON COMMIT DELETE ROWS ");
break;
case ONCOMMIT_DROP:
appendStringInfoString(str, "ON COMMIT DROP ");
break;
}
if (create_stmt->tablespacename != NULL)
{
appendStringInfoString(str, "TABLESPACE ");
appendStringInfoString(str, quote_identifier(create_stmt->tablespacename));
}
removeTrailingSpace(str);
}
static void deparseCreateFdwStmt(StringInfo str, CreateFdwStmt *create_fdw_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE FOREIGN DATA WRAPPER ");
appendStringInfoString(str, quote_identifier(create_fdw_stmt->fdwname));
appendStringInfoChar(str, ' ');
if (list_length(create_fdw_stmt->func_options) > 0)
{
deparseFdwOptions(str, create_fdw_stmt->func_options);
appendStringInfoChar(str, ' ');
}
deparseCreateGenericOptions(str, create_fdw_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterFdwStmt(StringInfo str, AlterFdwStmt *alter_fdw_stmt)
{
appendStringInfoString(str, "ALTER FOREIGN DATA WRAPPER ");
appendStringInfoString(str, quote_identifier(alter_fdw_stmt->fdwname));
appendStringInfoChar(str, ' ');
if (list_length(alter_fdw_stmt->func_options) > 0)
{
deparseFdwOptions(str, alter_fdw_stmt->func_options);
appendStringInfoChar(str, ' ');
}
if (list_length(alter_fdw_stmt->options) > 0)
deparseAlterGenericOptions(str, alter_fdw_stmt->options);
removeTrailingSpace(str);
}
static void deparseCreateForeignServerStmt(StringInfo str, CreateForeignServerStmt *create_foreign_server_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE SERVER ");
if (create_foreign_server_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->servername));
appendStringInfoChar(str, ' ');
if (create_foreign_server_stmt->servertype != NULL)
{
appendStringInfoString(str, "TYPE ");
deparseStringLiteral(str, create_foreign_server_stmt->servertype);
appendStringInfoChar(str, ' ');
}
if (create_foreign_server_stmt->version != NULL)
{
appendStringInfoString(str, "VERSION ");
deparseStringLiteral(str, create_foreign_server_stmt->version);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
appendStringInfoString(str, quote_identifier(create_foreign_server_stmt->fdwname));
appendStringInfoChar(str, ' ');
deparseCreateGenericOptions(str, create_foreign_server_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterForeignServerStmt(StringInfo str, AlterForeignServerStmt *alter_foreign_server_stmt)
{
appendStringInfoString(str, "ALTER SERVER ");
appendStringInfoString(str, quote_identifier(alter_foreign_server_stmt->servername));
appendStringInfoChar(str, ' ');
if (alter_foreign_server_stmt->has_version)
{
appendStringInfoString(str, "VERSION ");
if (alter_foreign_server_stmt->version != NULL)
deparseStringLiteral(str, alter_foreign_server_stmt->version);
else
appendStringInfoString(str, "NULL");
appendStringInfoChar(str, ' ');
}
if (list_length(alter_foreign_server_stmt->options) > 0)
deparseAlterGenericOptions(str, alter_foreign_server_stmt->options);
removeTrailingSpace(str);
}
static void deparseCreateUserMappingStmt(StringInfo str, CreateUserMappingStmt *create_user_mapping_stmt)
{
appendStringInfoString(str, "CREATE USER MAPPING ");
if (create_user_mapping_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
appendStringInfoString(str, "FOR ");
deparseRoleSpec(str, create_user_mapping_stmt->user);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "SERVER ");
appendStringInfoString(str, quote_identifier(create_user_mapping_stmt->servername));
appendStringInfoChar(str, ' ');
deparseCreateGenericOptions(str, create_user_mapping_stmt->options);
removeTrailingSpace(str);
}
static void deparseCreatedbStmt(StringInfo str, CreatedbStmt *createdb_stmt)
{
appendStringInfoString(str, "CREATE DATABASE ");
deparseColId(str, createdb_stmt->dbname);
appendStringInfoChar(str, ' ');
deparseCreatedbOptList(str, createdb_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterUserMappingStmt(StringInfo str, AlterUserMappingStmt *alter_user_mapping_stmt)
{
appendStringInfoString(str, "ALTER USER MAPPING FOR ");
deparseRoleSpec(str, alter_user_mapping_stmt->user);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "SERVER ");
appendStringInfoString(str, quote_identifier(alter_user_mapping_stmt->servername));
appendStringInfoChar(str, ' ');
deparseAlterGenericOptions(str, alter_user_mapping_stmt->options);
removeTrailingSpace(str);
}
static void deparseDropUserMappingStmt(StringInfo str, DropUserMappingStmt *drop_user_mapping_stmt)
{
appendStringInfoString(str, "DROP USER MAPPING ");
if (drop_user_mapping_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
appendStringInfoString(str, "FOR ");
deparseRoleSpec(str, drop_user_mapping_stmt->user);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "SERVER ");
appendStringInfoString(str, quote_identifier(drop_user_mapping_stmt->servername));
}
static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "SECURITY LABEL ");
if (sec_label_stmt->provider != NULL)
{
appendStringInfoString(str, "FOR ");
appendStringInfoString(str, quote_identifier(sec_label_stmt->provider));
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "ON ");
switch (sec_label_stmt->objtype)
{
case OBJECT_COLUMN:
appendStringInfoString(str, "COLUMN ");
deparseAnyName(str, castNode(List, sec_label_stmt->object));
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
deparseAnyName(str, castNode(List, sec_label_stmt->object));
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
deparseAnyName(str, castNode(List, sec_label_stmt->object));
break;
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
deparseAnyName(str, castNode(List, sec_label_stmt->object));
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
deparseAnyName(str, castNode(List, sec_label_stmt->object));
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
deparseAnyName(str, castNode(List, sec_label_stmt->object));
break;
case OBJECT_DATABASE:
appendStringInfoString(str, "DATABASE ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, "EVENT TRIGGER ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_PUBLICATION:
appendStringInfoString(str, "PUBLICATION ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_ROLE:
appendStringInfoString(str, "ROLE ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_SUBSCRIPTION:
appendStringInfoString(str, "SUBSCRIPTION ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_TABLESPACE:
appendStringInfoString(str, "TABLESPACE ");
appendStringInfoString(str, quote_identifier(strVal(sec_label_stmt->object)));
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
deparseTypeName(str, castNode(TypeName, sec_label_stmt->object));
break;
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
break;
case OBJECT_LARGEOBJECT:
appendStringInfoString(str, "LARGE OBJECT ");
deparseValue(str, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, sec_label_stmt->object));
break;
default:
Assert(false);
break;
}
appendStringInfoString(str, " IS ");
if (sec_label_stmt->label != NULL)
deparseStringLiteral(str, sec_label_stmt->label);
else
appendStringInfoString(str, "NULL");
}
static void deparseCreateForeignTableStmt(StringInfo str, CreateForeignTableStmt *create_foreign_table_stmt)
{
ListCell *lc;
deparseCreateStmt(str, &create_foreign_table_stmt->base, true);
appendStringInfoString(str, " SERVER ");
appendStringInfoString(str, quote_identifier(create_foreign_table_stmt->servername));
appendStringInfoChar(str, ' ');
if (list_length(create_foreign_table_stmt->options) > 0)
deparseAlterGenericOptions(str, create_foreign_table_stmt->options);
removeTrailingSpace(str);
}
static void deparseImportForeignSchemaStmt(StringInfo str, ImportForeignSchemaStmt *import_foreign_schema_stmt)
{
appendStringInfoString(str, "IMPORT FOREIGN SCHEMA ");
appendStringInfoString(str, import_foreign_schema_stmt->remote_schema);
appendStringInfoChar(str, ' ');
switch (import_foreign_schema_stmt->list_type)
{
case FDW_IMPORT_SCHEMA_ALL:
break;
case FDW_IMPORT_SCHEMA_LIMIT_TO:
appendStringInfoString(str, "LIMIT TO (");
deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
appendStringInfoString(str, ") ");
break;
case FDW_IMPORT_SCHEMA_EXCEPT:
appendStringInfoString(str, "EXCEPT (");
deparseRelationExprList(str, import_foreign_schema_stmt->table_list);
appendStringInfoString(str, ") ");
break;
}
appendStringInfoString(str, "FROM SERVER ");
appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->server_name));
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "INTO ");
appendStringInfoString(str, quote_identifier(import_foreign_schema_stmt->local_schema));
appendStringInfoChar(str, ' ');
deparseCreateGenericOptions(str, import_foreign_schema_stmt->options);
removeTrailingSpace(str);
}
static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_table_as_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
switch (create_table_as_stmt->objtype)
{
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
default:
Assert(false);
break;
}
if (create_table_as_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
deparseIntoClause(str, create_table_as_stmt->into);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "AS ");
if (IsA(create_table_as_stmt->query, ExecuteStmt))
deparseExecuteStmt(str, castNode(ExecuteStmt, create_table_as_stmt->query));
else
deparseSelectStmt(str, castNode(SelectStmt, create_table_as_stmt->query));
appendStringInfoChar(str, ' ');
if (create_table_as_stmt->into->skipData)
appendStringInfoString(str, "WITH NO DATA ");
removeTrailingSpace(str);
}
static void deparseViewStmt(StringInfo str, ViewStmt *view_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
if (view_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
deparseOptTemp(str, view_stmt->view->relpersistence);
appendStringInfoString(str, "VIEW ");
deparseRangeVar(str, view_stmt->view, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (list_length(view_stmt->aliases) > 0)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, view_stmt->aliases);
appendStringInfoString(str, ") ");
}
deparseOptWith(str, view_stmt->options);
appendStringInfoString(str, "AS ");
deparseSelectStmt(str, castNode(SelectStmt, view_stmt->query));
appendStringInfoChar(str, ' ');
switch (view_stmt->withCheckOption)
{
case NO_CHECK_OPTION:
break;
case LOCAL_CHECK_OPTION:
appendStringInfoString(str, "WITH LOCAL CHECK OPTION ");
break;
case CASCADED_CHECK_OPTION:
appendStringInfoString(str, "WITH CHECK OPTION ");
break;
}
removeTrailingSpace(str);
}
static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
{
ListCell *lc;
List *l;
appendStringInfoString(str, "DROP ");
switch (drop_stmt->removeType)
{
case OBJECT_ACCESS_METHOD:
appendStringInfoString(str, "ACCESS METHOD ");
break;
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
break;
case OBJECT_CAST:
appendStringInfoString(str, "CAST ");
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
break;
case OBJECT_CONVERSION:
appendStringInfoString(str, "CONVERSION ");
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
break;
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, "EVENT TRIGGER ");
break;
case OBJECT_EXTENSION:
appendStringInfoString(str, "EXTENSION ");
break;
case OBJECT_FDW:
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
break;
case OBJECT_FOREIGN_SERVER:
appendStringInfoString(str, "SERVER ");
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
break;
case OBJECT_INDEX:
appendStringInfoString(str, "INDEX ");
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
case OBJECT_OPCLASS:
appendStringInfoString(str, "OPERATOR CLASS ");
break;
case OBJECT_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
break;
case OBJECT_OPFAMILY:
appendStringInfoString(str, "OPERATOR FAMILY ");
break;
case OBJECT_POLICY:
appendStringInfoString(str, "POLICY ");
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
break;
case OBJECT_PUBLICATION:
appendStringInfoString(str, "PUBLICATION ");
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
break;
case OBJECT_RULE:
appendStringInfoString(str, "RULE ");
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
break;
case OBJECT_STATISTIC_EXT:
appendStringInfoString(str, "STATISTICS ");
break;
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_TRANSFORM:
appendStringInfoString(str, "TRANSFORM ");
break;
case OBJECT_TRIGGER:
appendStringInfoString(str, "TRIGGER ");
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
break;
case OBJECT_TSPARSER:
appendStringInfoString(str, "TEXT SEARCH PARSER ");
break;
case OBJECT_TSTEMPLATE:
appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
break;
default:
Assert(false);
}
if (drop_stmt->concurrent)
appendStringInfoString(str, "CONCURRENTLY ");
if (drop_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
switch (drop_stmt->removeType)
{
case OBJECT_TABLE:
case OBJECT_SEQUENCE:
case OBJECT_VIEW:
case OBJECT_MATVIEW:
case OBJECT_INDEX:
case OBJECT_FOREIGN_TABLE:
case OBJECT_COLLATION:
case OBJECT_CONVERSION:
case OBJECT_STATISTIC_EXT:
case OBJECT_TSPARSER:
case OBJECT_TSDICTIONARY:
case OBJECT_TSTEMPLATE:
case OBJECT_TSCONFIGURATION:
deparseAnyNameList(str, drop_stmt->objects);
appendStringInfoChar(str, ' ');
break;
case OBJECT_ACCESS_METHOD:
case OBJECT_EVENT_TRIGGER:
case OBJECT_EXTENSION:
case OBJECT_FDW:
case OBJECT_PUBLICATION:
case OBJECT_SCHEMA:
case OBJECT_FOREIGN_SERVER:
deparseNameList(str, drop_stmt->objects);
appendStringInfoChar(str, ' ');
break;
case OBJECT_POLICY:
case OBJECT_RULE:
case OBJECT_TRIGGER:
Assert(list_length(drop_stmt->objects) == 1);
l = linitial(drop_stmt->objects);
deparseColId(str, strVal(llast(l)));
appendStringInfoString(str, " ON ");
deparseAnyNameSkipLast(str, l);
appendStringInfoChar(str, ' ');
break;
case OBJECT_CAST:
Assert(list_length(drop_stmt->objects) == 1);
l = linitial(drop_stmt->objects);
Assert(list_length(l) == 2);
appendStringInfoChar(str, '(');
deparseTypeName(str, castNode(TypeName, linitial(l)));
appendStringInfoString(str, " AS ");
deparseTypeName(str, castNode(TypeName, lsecond(l)));
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
break;
case OBJECT_OPFAMILY:
case OBJECT_OPCLASS:
Assert(list_length(drop_stmt->objects) == 1);
l = linitial(drop_stmt->objects);
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
deparseColId(str, strVal(linitial(l)));
appendStringInfoChar(str, ' ');
break;
case OBJECT_TRANSFORM:
Assert(list_length(drop_stmt->objects) == 1);
l = linitial(drop_stmt->objects);
appendStringInfoString(str, "FOR ");
deparseTypeName(str, castNode(TypeName, linitial(l)));
appendStringInfoString(str, " LANGUAGE ");
deparseColId(str, strVal(lsecond(l)));
appendStringInfoChar(str, ' ');
break;
case OBJECT_LANGUAGE:
deparseNameList(str, drop_stmt->objects);
appendStringInfoChar(str, ' ');
break;
case OBJECT_TYPE:
case OBJECT_DOMAIN:
foreach(lc, drop_stmt->objects)
{
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
if (lnext(drop_stmt->objects, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
break;
case OBJECT_AGGREGATE:
foreach(lc, drop_stmt->objects)
{
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
if (lnext(drop_stmt->objects, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
break;
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
case OBJECT_ROUTINE:
foreach(lc, drop_stmt->objects)
{
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
if (lnext(drop_stmt->objects, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
break;
case OBJECT_OPERATOR:
foreach(lc, drop_stmt->objects)
{
deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
if (lnext(drop_stmt->objects, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
break;
default:
Assert(false);
}
deparseOptDropBehavior(str, drop_stmt->behavior);
removeTrailingSpace(str);
}
static void deparseGroupingSet(StringInfo str, GroupingSet *grouping_set)
{
switch(grouping_set->kind)
{
case GROUPING_SET_EMPTY:
appendStringInfoString(str, "()");
break;
case GROUPING_SET_SIMPLE:
Assert(false);
break;
case GROUPING_SET_ROLLUP:
appendStringInfoString(str, "ROLLUP (");
deparseExprList(str, grouping_set->content);
appendStringInfoChar(str, ')');
break;
case GROUPING_SET_CUBE:
appendStringInfoString(str, "CUBE (");
deparseExprList(str, grouping_set->content);
appendStringInfoChar(str, ')');
break;
case GROUPING_SET_SETS:
appendStringInfoString(str, "GROUPING SETS (");
deparseGroupByList(str, grouping_set->content);
appendStringInfoChar(str, ')');
break;
}
}
static void deparseDropTableSpaceStmt(StringInfo str, DropTableSpaceStmt *drop_table_space_stmt)
{
appendStringInfoString(str, "DROP TABLESPACE ");
if (drop_table_space_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
appendStringInfoString(str, drop_table_space_stmt->tablespacename);
}
static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt *alter_object_depends_stmt)
{
appendStringInfoString(str, "ALTER ");
switch (alter_object_depends_stmt->objectType)
{
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_depends_stmt->object));
break;
case OBJECT_TRIGGER:
appendStringInfoString(str, "TRIGGER ");
deparseColId(str, strVal(linitial(castNode(List, alter_object_depends_stmt->object))));
appendStringInfoString(str, " ON ");
deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_INDEX:
appendStringInfoString(str, "INDEX ");
deparseRangeVar(str, alter_object_depends_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
default:
Assert(false);
}
appendStringInfoChar(str, ' ');
if (alter_object_depends_stmt->remove)
appendStringInfoString(str, "NO ");
appendStringInfo(str, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
}
static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
{
List *l = NULL;
ListCell *lc = NULL;
appendStringInfoString(str, "ALTER ");
switch (alter_object_schema_stmt->objectType)
{
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_CONVERSION:
appendStringInfoString(str, "CONVERSION ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_EXTENSION:
appendStringInfoString(str, "EXTENSION ");
appendStringInfoString(str, quote_identifier(strVal(alter_object_schema_stmt->object)));
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
break;
case OBJECT_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
break;
case OBJECT_OPCLASS:
l = castNode(List, alter_object_schema_stmt->object);
appendStringInfoString(str, "OPERATOR CLASS ");
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
break;
case OBJECT_OPFAMILY:
l = castNode(List, alter_object_schema_stmt->object);
appendStringInfoString(str, "OPERATOR FAMILY ");
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_object_schema_stmt->object));
break;
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
if (alter_object_schema_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_STATISTIC_EXT:
appendStringInfoString(str, "STATISTICS ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_TSPARSER:
appendStringInfoString(str, "TEXT SEARCH PARSER ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_TSTEMPLATE:
appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
if (alter_object_schema_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
if (alter_object_schema_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
if (alter_object_schema_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
if (alter_object_schema_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_object_schema_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
deparseAnyName(str, castNode(List, alter_object_schema_stmt->object));
break;
default:
Assert(false);
break;
}
appendStringInfoString(str, " SET SCHEMA ");
appendStringInfoString(str, quote_identifier(alter_object_schema_stmt->newschema));
}
static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd, DeparseNodeContext context)
{
ListCell *lc = NULL;
const char *options = NULL;
bool trailing_missing_ok = false;
switch (alter_table_cmd->subtype)
{
case AT_AddColumn:
if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "ADD ATTRIBUTE ");
else
appendStringInfoString(str, "ADD COLUMN ");
break;
case AT_AddColumnToView:
Assert(false);
break;
case AT_ColumnDefault:
appendStringInfoString(str, "ALTER COLUMN ");
if (alter_table_cmd->def != NULL)
options = "SET DEFAULT";
else
options = "DROP DEFAULT";
break;
case AT_CookedColumnDefault:
Assert(false);
break;
case AT_DropNotNull:
appendStringInfoString(str, "ALTER COLUMN ");
options = "DROP NOT NULL";
break;
case AT_SetNotNull:
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET NOT NULL";
break;
case AT_DropExpression:
appendStringInfoString(str, "ALTER COLUMN ");
options = "DROP EXPRESSION";
trailing_missing_ok = true;
break;
case AT_CheckNotNull:
Assert(false);
break;
case AT_SetStatistics:
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET STATISTICS";
break;
case AT_SetOptions:
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET";
break;
case AT_ResetOptions:
appendStringInfoString(str, "ALTER COLUMN ");
options = "RESET";
break;
case AT_SetStorage:
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET STORAGE";
break;
case AT_SetCompression:
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET COMPRESSION";
break;
case AT_DropColumn:
if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "DROP ATTRIBUTE ");
else
appendStringInfoString(str, "DROP ");
break;
case AT_AddIndex:
appendStringInfoString(str, "ADD INDEX ");
break;
case AT_ReAddIndex:
Assert(false);
break;
case AT_AddConstraint:
appendStringInfoString(str, "ADD ");
break;
case AT_ReAddConstraint:
Assert(false);
break;
case AT_ReAddDomainConstraint:
Assert(false);
break;
case AT_AlterConstraint:
appendStringInfoString(str, "ALTER "); break;
case AT_ValidateConstraint:
appendStringInfoString(str, "VALIDATE CONSTRAINT ");
break;
case AT_AddIndexConstraint:
Assert(false);
break;
case AT_DropConstraint:
appendStringInfoString(str, "DROP CONSTRAINT ");
break;
case AT_ReAddComment:
case AT_ReAddStatistics:
Assert(false);
break;
case AT_AlterColumnType:
if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "ALTER ATTRIBUTE ");
else
appendStringInfoString(str, "ALTER COLUMN ");
options = "TYPE";
break;
case AT_AlterColumnGenericOptions:
appendStringInfoString(str, "ALTER COLUMN ");
break;
case AT_ChangeOwner:
appendStringInfoString(str, "OWNER TO ");
deparseRoleSpec(str, alter_table_cmd->newowner);
break;
case AT_ClusterOn:
appendStringInfoString(str, "CLUSTER ON ");
break;
case AT_DropCluster:
appendStringInfoString(str, "SET WITHOUT CLUSTER ");
break;
case AT_SetLogged:
appendStringInfoString(str, "SET LOGGED ");
break;
case AT_SetUnLogged:
appendStringInfoString(str, "SET UNLOGGED ");
break;
case AT_DropOids:
appendStringInfoString(str, "SET WITHOUT OIDS ");
break;
case AT_SetTableSpace:
appendStringInfoString(str, "SET TABLESPACE ");
break;
case AT_SetRelOptions:
appendStringInfoString(str, "SET ");
break;
case AT_SetAccessMethod:
appendStringInfo(str, "SET ACCESS METHOD ");
break;
case AT_ResetRelOptions:
appendStringInfoString(str, "RESET ");
break;
case AT_ReplaceRelOptions:
Assert(false);
break;
case AT_EnableTrig:
appendStringInfoString(str, "ENABLE TRIGGER ");
break;
case AT_EnableAlwaysTrig:
appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
break;
case AT_EnableReplicaTrig:
appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
break;
case AT_DisableTrig:
appendStringInfoString(str, "DISABLE TRIGGER ");
break;
case AT_EnableTrigAll:
appendStringInfoString(str, "ENABLE TRIGGER ALL ");
break;
case AT_DisableTrigAll:
appendStringInfoString(str, "DISABLE TRIGGER ALL ");
break;
case AT_EnableTrigUser:
appendStringInfoString(str, "ENABLE TRIGGER USER ");
break;
case AT_DisableTrigUser:
appendStringInfoString(str, "DISABLE TRIGGER USER ");
break;
case AT_EnableRule:
appendStringInfoString(str, "ENABLE RULE ");
break;
case AT_EnableAlwaysRule:
appendStringInfoString(str, "ENABLE ALWAYS RULE ");
break;
case AT_EnableReplicaRule:
appendStringInfoString(str, "ENABLE REPLICA RULE ");
break;
case AT_DisableRule:
appendStringInfoString(str, "DISABLE RULE ");
break;
case AT_AddInherit:
appendStringInfoString(str, "INHERIT ");
break;
case AT_DropInherit:
appendStringInfoString(str, "NO INHERIT ");
break;
case AT_AddOf:
appendStringInfoString(str, "OF ");
break;
case AT_DropOf:
appendStringInfoString(str, "NOT OF ");
break;
case AT_ReplicaIdentity:
appendStringInfoString(str, "REPLICA IDENTITY ");
break;
case AT_EnableRowSecurity:
appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
break;
case AT_DisableRowSecurity:
appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
break;
case AT_ForceRowSecurity:
appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
break;
case AT_NoForceRowSecurity:
appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
break;
case AT_GenericOptions:
break;
case AT_AttachPartition:
appendStringInfoString(str, "ATTACH PARTITION ");
break;
case AT_DetachPartition:
appendStringInfoString(str, "DETACH PARTITION ");
break;
case AT_DetachPartitionFinalize:
appendStringInfoString(str, "DETACH PARTITION ");
break;
case AT_AddIdentity:
appendStringInfoString(str, "ALTER ");
options = "ADD";
break;
case AT_SetIdentity:
appendStringInfoString(str, "ALTER ");
break;
case AT_DropIdentity:
appendStringInfoString(str, "ALTER COLUMN ");
options = "DROP IDENTITY";
trailing_missing_ok = true;
break;
case AT_SetExpression:
appendStringInfoString(str, "ALTER COLUMN ");
break;
}
if (alter_table_cmd->missing_ok && !trailing_missing_ok)
{
if (alter_table_cmd->subtype == AT_AddColumn)
appendStringInfoString(str, "IF NOT EXISTS ");
else
appendStringInfoString(str, "IF EXISTS ");
}
if (alter_table_cmd->name != NULL)
{
appendStringInfoString(str, quote_identifier(alter_table_cmd->name));
appendStringInfoChar(str, ' ');
} else if (alter_table_cmd->subtype == AT_SetAccessMethod)
{
appendStringInfoString(str, " DEFAULT");
}
if (alter_table_cmd->num > 0)
appendStringInfo(str, "%d ", alter_table_cmd->num);
if (options != NULL)
{
appendStringInfoString(str, options);
appendStringInfoChar(str, ' ');
}
if (alter_table_cmd->missing_ok && trailing_missing_ok)
appendStringInfoString(str, "IF EXISTS ");
switch (alter_table_cmd->subtype)
{
case AT_AttachPartition:
case AT_DetachPartition:
deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_DetachPartitionFinalize:
deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
appendStringInfoString(str, "FINALIZE ");
break;
case AT_AddColumn:
case AT_AlterColumnType:
deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_ColumnDefault:
if (alter_table_cmd->def != NULL)
{
deparseExpr(str, alter_table_cmd->def, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
}
break;
case AT_SetStatistics:
deparseSignedIconst(str, alter_table_cmd->def);
appendStringInfoChar(str, ' ');
break;
case AT_SetOptions:
case AT_ResetOptions:
case AT_SetRelOptions:
case AT_ResetRelOptions:
deparseRelOptions(str, castNode(List, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_SetStorage:
deparseColId(str, strVal(alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_SetCompression:
if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
appendStringInfoString(str, "DEFAULT");
else
deparseColId(str, strVal(alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_AddIdentity:
case AT_AddConstraint:
case AT_AlterConstraint:
deparseConstraint(str, castNode(Constraint, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_SetIdentity:
deparseAlterIdentityColumnOptionList(str, castNode(List, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_AlterColumnGenericOptions:
case AT_GenericOptions:
deparseAlterGenericOptions(str, castNode(List, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_AddInherit:
case AT_DropInherit:
deparseRangeVar(str, castNode(RangeVar, alter_table_cmd->def), DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
break;
case AT_AddOf:
deparseTypeName(str, castNode(TypeName, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_ReplicaIdentity:
deparseReplicaIdentityStmt(str, castNode(ReplicaIdentityStmt, alter_table_cmd->def));
appendStringInfoChar(str, ' ');
break;
case AT_SetExpression:
appendStringInfoString(str, "SET EXPRESSION AS (");
deparseExpr(str, alter_table_cmd->def, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
break;
default:
Assert(alter_table_cmd->def == NULL);
break;
}
deparseOptDropBehavior(str, alter_table_cmd->behavior);
removeTrailingSpace(str);
}
static DeparseNodeContext deparseAlterTableObjType(StringInfo str, ObjectType type)
{
switch (type)
{
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
break;
case OBJECT_INDEX:
appendStringInfoString(str, "INDEX ");
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
break;
default:
Assert(false);
break;
}
return DEPARSE_NODE_CONTEXT_NONE;
}
static void deparseAlterTableMoveAllStmt(StringInfo str, AlterTableMoveAllStmt *move_all_stmt)
{
appendStringInfoString(str, "ALTER ");
deparseAlterTableObjType(str, move_all_stmt->objtype);
appendStringInfoString(str, "ALL IN TABLESPACE ");
appendStringInfoString(str, move_all_stmt->orig_tablespacename);
appendStringInfoChar(str, ' ');
if (move_all_stmt->roles)
{
appendStringInfoString(str, "OWNED BY ");
deparseRoleList(str, move_all_stmt->roles);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "SET TABLESPACE ");
appendStringInfoString(str, move_all_stmt->new_tablespacename);
appendStringInfoChar(str, ' ');
if (move_all_stmt->nowait)
{
appendStringInfoString(str, "NOWAIT");
}
}
static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
{
ListCell *lc;
appendStringInfoString(str, "ALTER ");
DeparseNodeContext context = deparseAlterTableObjType(str, alter_table_stmt->objtype);
if (alter_table_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_table_stmt->relation, context);
appendStringInfoChar(str, ' ');
foreach(lc, alter_table_stmt->cmds)
{
deparseAlterTableCmd(str, castNode(AlterTableCmd, lfirst(lc)), context);
if (lnext(alter_table_stmt->cmds, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseAlterTableSpaceOptionsStmt(StringInfo str, AlterTableSpaceOptionsStmt *alter_table_space_options_stmt)
{
appendStringInfoString(str, "ALTER TABLESPACE ");
deparseColId(str, alter_table_space_options_stmt->tablespacename);
appendStringInfoChar(str, ' ');
if (alter_table_space_options_stmt->isReset)
appendStringInfoString(str, "RESET ");
else
appendStringInfoString(str, "SET ");
deparseRelOptions(str, alter_table_space_options_stmt->options);
}
static void deparseAlterDomainStmt(StringInfo str, AlterDomainStmt *alter_domain_stmt)
{
appendStringInfoString(str, "ALTER DOMAIN ");
deparseAnyName(str, alter_domain_stmt->typeName);
appendStringInfoChar(str, ' ');
switch (alter_domain_stmt->subtype)
{
case 'T':
if (alter_domain_stmt->def != NULL)
{
appendStringInfoString(str, "SET DEFAULT ");
deparseExpr(str, alter_domain_stmt->def, DEPARSE_NODE_CONTEXT_A_EXPR);
}
else
{
appendStringInfoString(str, "DROP DEFAULT");
}
break;
case 'N':
appendStringInfoString(str, "DROP NOT NULL");
break;
case 'O':
appendStringInfoString(str, "SET NOT NULL");
break;
case 'C':
appendStringInfoString(str, "ADD ");
deparseConstraint(str, castNode(Constraint, alter_domain_stmt->def));
break;
case 'X':
appendStringInfoString(str, "DROP CONSTRAINT ");
if (alter_domain_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
if (alter_domain_stmt->behavior == DROP_CASCADE)
appendStringInfoString(str, " CASCADE");
break;
case 'V':
appendStringInfoString(str, "VALIDATE CONSTRAINT ");
appendStringInfoString(str, quote_identifier(alter_domain_stmt->name));
break;
default:
Assert(false);
}
}
static void deparseRenameStmt(StringInfo str, RenameStmt *rename_stmt)
{
List *l = NULL;
appendStringInfoString(str, "ALTER ");
switch (rename_stmt->renameType)
{
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
break;
case OBJECT_CONVERSION:
appendStringInfoString(str, "CONVERSION ");
break;
case OBJECT_DATABASE:
appendStringInfoString(str, "DATABASE ");
break;
case OBJECT_DOMAIN:
case OBJECT_DOMCONSTRAINT:
appendStringInfoString(str, "DOMAIN ");
break;
case OBJECT_FDW:
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
break;
case OBJECT_ROLE:
appendStringInfoString(str, "ROLE ");
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
break;
case OBJECT_OPCLASS:
appendStringInfoString(str, "OPERATOR CLASS ");
break;
case OBJECT_OPFAMILY:
appendStringInfoString(str, "OPERATOR FAMILY ");
break;
case OBJECT_POLICY:
appendStringInfoString(str, "POLICY ");
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
break;
case OBJECT_PUBLICATION:
appendStringInfoString(str, "PUBLICATION ");
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
break;
case OBJECT_FOREIGN_SERVER:
appendStringInfoString(str, "SERVER ");
break;
case OBJECT_SUBSCRIPTION:
appendStringInfoString(str, "SUBSCRIPTION ");
break;
case OBJECT_TABLE:
case OBJECT_TABCONSTRAINT:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_COLUMN:
switch (rename_stmt->relationType)
{
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
default:
Assert(false);
}
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
case OBJECT_INDEX:
appendStringInfoString(str, "INDEX ");
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
break;
case OBJECT_RULE:
appendStringInfoString(str, "RULE ");
break;
case OBJECT_TRIGGER:
appendStringInfoString(str, "TRIGGER ");
break;
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, "EVENT TRIGGER ");
break;
case OBJECT_TABLESPACE:
appendStringInfoString(str, "TABLESPACE ");
break;
case OBJECT_STATISTIC_EXT:
appendStringInfoString(str, "STATISTICS ");
break;
case OBJECT_TSPARSER:
appendStringInfoString(str, "TEXT SEARCH PARSER ");
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
break;
case OBJECT_TSTEMPLATE:
appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
break;
case OBJECT_TYPE:
case OBJECT_ATTRIBUTE:
appendStringInfoString(str, "TYPE ");
break;
default:
Assert(false);
break;
}
if (rename_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
switch (rename_stmt->renameType)
{
case OBJECT_AGGREGATE:
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_DOMCONSTRAINT:
deparseAnyName(str, castNode(List, rename_stmt->object));
appendStringInfoString(str, " RENAME CONSTRAINT ");
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoChar(str, ' ');
break;
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
l = castNode(List, rename_stmt->object);
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_POLICY:
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoString(str, " ON ");
deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
case OBJECT_ROUTINE:
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, rename_stmt->object));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_SUBSCRIPTION:
deparseColId(str, strVal(rename_stmt->object));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_TABLE:
case OBJECT_SEQUENCE:
case OBJECT_VIEW:
case OBJECT_MATVIEW:
case OBJECT_INDEX:
case OBJECT_FOREIGN_TABLE:
deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_COLUMN:
deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoString(str, " RENAME COLUMN ");
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoChar(str, ' ');
break;
case OBJECT_TABCONSTRAINT:
deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoString(str, " RENAME CONSTRAINT ");
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoChar(str, ' ');
break;
case OBJECT_RULE:
case OBJECT_TRIGGER:
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoString(str, " ON ");
deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_FDW:
case OBJECT_LANGUAGE:
case OBJECT_PUBLICATION:
case OBJECT_FOREIGN_SERVER:
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, quote_identifier(strVal(rename_stmt->object)));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_DATABASE:
case OBJECT_ROLE:
case OBJECT_SCHEMA:
case OBJECT_TABLESPACE:
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_COLLATION:
case OBJECT_CONVERSION:
case OBJECT_DOMAIN:
case OBJECT_STATISTIC_EXT:
case OBJECT_TSPARSER:
case OBJECT_TSDICTIONARY:
case OBJECT_TSTEMPLATE:
case OBJECT_TSCONFIGURATION:
case OBJECT_TYPE:
deparseAnyName(str, castNode(List, rename_stmt->object));
appendStringInfoString(str, " RENAME ");
break;
case OBJECT_ATTRIBUTE:
deparseRangeVar(str, rename_stmt->relation, DEPARSE_NODE_CONTEXT_ALTER_TYPE);
appendStringInfoString(str, " RENAME ATTRIBUTE ");
appendStringInfoString(str, quote_identifier(rename_stmt->subname));
appendStringInfoChar(str, ' ');
break;
default:
Assert(false);
break;
}
appendStringInfoString(str, "TO ");
appendStringInfoString(str, quote_identifier(rename_stmt->newname));
appendStringInfoChar(str, ' ');
deparseOptDropBehavior(str, rename_stmt->behavior);
removeTrailingSpace(str);
}
static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_stmt)
{
ListCell *lc;
switch (transaction_stmt->kind)
{
case TRANS_STMT_BEGIN:
appendStringInfoString(str, "BEGIN ");
deparseTransactionModeList(str, transaction_stmt->options);
break;
case TRANS_STMT_START:
appendStringInfoString(str, "START TRANSACTION ");
deparseTransactionModeList(str, transaction_stmt->options);
break;
case TRANS_STMT_COMMIT:
appendStringInfoString(str, "COMMIT ");
if (transaction_stmt->chain)
appendStringInfoString(str, "AND CHAIN ");
break;
case TRANS_STMT_ROLLBACK:
appendStringInfoString(str, "ROLLBACK ");
if (transaction_stmt->chain)
appendStringInfoString(str, "AND CHAIN ");
break;
case TRANS_STMT_SAVEPOINT:
appendStringInfoString(str, "SAVEPOINT ");
appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
break;
case TRANS_STMT_RELEASE:
appendStringInfoString(str, "RELEASE ");
appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
break;
case TRANS_STMT_ROLLBACK_TO:
appendStringInfoString(str, "ROLLBACK ");
appendStringInfoString(str, "TO SAVEPOINT ");
appendStringInfoString(str, quote_identifier(transaction_stmt->savepoint_name));
break;
case TRANS_STMT_PREPARE:
appendStringInfoString(str, "PREPARE TRANSACTION ");
deparseStringLiteral(str, transaction_stmt->gid);
break;
case TRANS_STMT_COMMIT_PREPARED:
appendStringInfoString(str, "COMMIT PREPARED ");
deparseStringLiteral(str, transaction_stmt->gid);
break;
case TRANS_STMT_ROLLBACK_PREPARED:
appendStringInfoString(str, "ROLLBACK PREPARED ");
deparseStringLiteral(str, transaction_stmt->gid);
break;
}
removeTrailingSpace(str);
}
static bool isSetTimeZoneInterval(VariableSetStmt* stmt)
{
if (!(strcmp(stmt->name, "timezone") == 0 &&
list_length(stmt->args) == 1 &&
IsA(linitial(stmt->args), TypeCast)))
return false;
TypeName* typeName = castNode(TypeCast, linitial(stmt->args))->typeName;
return (list_length(typeName->names) == 2 &&
strcmp(strVal(linitial(typeName->names)), "pg_catalog") == 0 &&
strcmp(strVal(llast(typeName->names)), "interval") == 0);
}
static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
{
ListCell *lc;
switch (variable_set_stmt->kind)
{
case VAR_SET_VALUE:
appendStringInfoString(str, "SET ");
if (variable_set_stmt->is_local)
appendStringInfoString(str, "LOCAL ");
if (isSetTimeZoneInterval(variable_set_stmt))
{
appendStringInfoString(str, "TIME ZONE ");
deparseVarList(str, variable_set_stmt->args);
}
else
{
deparseVarName(str, variable_set_stmt->name);
appendStringInfoString(str, " TO ");
deparseVarList(str, variable_set_stmt->args);
}
break;
case VAR_SET_DEFAULT:
appendStringInfoString(str, "SET ");
if (variable_set_stmt->is_local)
appendStringInfoString(str, "LOCAL ");
deparseVarName(str, variable_set_stmt->name);
appendStringInfoString(str, " TO DEFAULT");
break;
case VAR_SET_CURRENT:
appendStringInfoString(str, "SET ");
if (variable_set_stmt->is_local)
appendStringInfoString(str, "LOCAL ");
deparseVarName(str, variable_set_stmt->name);
appendStringInfoString(str, " FROM CURRENT");
break;
case VAR_SET_MULTI:
Assert(variable_set_stmt->name != NULL);
appendStringInfoString(str, "SET ");
if (variable_set_stmt->is_local)
appendStringInfoString(str, "LOCAL ");
if (strcmp(variable_set_stmt->name, "TRANSACTION") == 0)
{
appendStringInfoString(str, "TRANSACTION ");
deparseTransactionModeList(str, variable_set_stmt->args);
}
else if (strcmp(variable_set_stmt->name, "SESSION CHARACTERISTICS") == 0)
{
appendStringInfoString(str, "SESSION CHARACTERISTICS AS TRANSACTION ");
deparseTransactionModeList(str, variable_set_stmt->args);
}
else if (strcmp(variable_set_stmt->name, "TRANSACTION SNAPSHOT") == 0)
{
appendStringInfoString(str, "TRANSACTION SNAPSHOT ");
deparseStringLiteral(str, strVal(&castNode(A_Const, linitial(variable_set_stmt->args))->val));
}
else
{
Assert(false);
}
break;
case VAR_RESET:
appendStringInfoString(str, "RESET ");
deparseVarName(str, variable_set_stmt->name);
break;
case VAR_RESET_ALL:
appendStringInfoString(str, "RESET ALL");
break;
}
}
static void deparseDropdbStmt(StringInfo str, DropdbStmt *dropdb_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "DROP DATABASE ");
if (dropdb_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
appendStringInfoString(str, quote_identifier(dropdb_stmt->dbname));
appendStringInfoChar(str, ' ');
if (list_length(dropdb_stmt->options) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, dropdb_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "force") == 0)
appendStringInfoString(str, "FORCE");
else
Assert(false);
if (lnext(dropdb_stmt->options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
removeTrailingSpace(str);
}
static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
{
ListCell *lc = NULL;
ListCell *lc2 = NULL;
if (vacuum_stmt->is_vacuumcmd)
appendStringInfoString(str, "VACUUM ");
else
appendStringInfoString(str, "ANALYZE ");
deparseUtilityOptionList(str, vacuum_stmt->options);
foreach(lc, vacuum_stmt->rels)
{
Assert(IsA(lfirst(lc), VacuumRelation));
VacuumRelation *rel = castNode(VacuumRelation, lfirst(lc));
deparseRangeVar(str, rel->relation, DEPARSE_NODE_CONTEXT_NONE);
if (list_length(rel->va_cols) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc2, rel->va_cols)
{
appendStringInfoString(str, quote_identifier(strVal(lfirst(lc2))));
if (lnext(rel->va_cols, lc2))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
if (lnext(vacuum_stmt->rels, lc))
appendStringInfoString(str, ", ");
}
removeTrailingSpace(str);
}
static void deparseLoadStmt(StringInfo str, LoadStmt *load_stmt)
{
appendStringInfoString(str, "LOAD ");
deparseStringLiteral(str, load_stmt->filename);
}
static void deparseLockStmt(StringInfo str, LockStmt *lock_stmt)
{
ListCell *lc;
appendStringInfoString(str, "LOCK TABLE ");
deparseRelationExprList(str, lock_stmt->relations);
appendStringInfoChar(str, ' ');
if (lock_stmt->mode != AccessExclusiveLock)
{
appendStringInfoString(str, "IN ");
switch (lock_stmt->mode)
{
case AccessShareLock:
appendStringInfoString(str, "ACCESS SHARE ");
break;
case RowShareLock:
appendStringInfoString(str, "ROW SHARE ");
break;
case RowExclusiveLock:
appendStringInfoString(str, "ROW EXCLUSIVE ");
break;
case ShareUpdateExclusiveLock:
appendStringInfoString(str, "SHARE UPDATE EXCLUSIVE ");
break;
case ShareLock:
appendStringInfoString(str, "SHARE ");
break;
case ShareRowExclusiveLock:
appendStringInfoString(str, "SHARE ROW EXCLUSIVE ");
break;
case ExclusiveLock:
appendStringInfoString(str, "EXCLUSIVE ");
break;
case AccessExclusiveLock:
appendStringInfoString(str, "ACCESS EXCLUSIVE ");
break;
default:
Assert(false);
break;
}
appendStringInfoString(str, "MODE ");
}
if (lock_stmt->nowait)
appendStringInfoString(str, "NOWAIT ");
removeTrailingSpace(str);
}
static void deparseConstraintsSetStmt(StringInfo str, ConstraintsSetStmt *constraints_set_stmt)
{
appendStringInfoString(str, "SET CONSTRAINTS ");
if (list_length(constraints_set_stmt->constraints) > 0)
{
deparseQualifiedNameList(str, constraints_set_stmt->constraints);
appendStringInfoChar(str, ' ');
}
else
{
appendStringInfoString(str, "ALL ");
}
if (constraints_set_stmt->deferred)
appendStringInfoString(str, "DEFERRED");
else
appendStringInfoString(str, "IMMEDIATE");
}
static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
{
ListCell *lc = NULL;
char *defname = NULL;
appendStringInfoString(str, "EXPLAIN ");
deparseUtilityOptionList(str, explain_stmt->options);
deparseExplainableStmt(str, explain_stmt->query);
}
static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
{
ListCell *lc = NULL;
ListCell *lc2 = NULL;
appendStringInfoString(str, "COPY ");
if (copy_stmt->relation != NULL)
{
deparseRangeVar(str, copy_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
if (list_length(copy_stmt->attlist) > 0)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, copy_stmt->attlist);
appendStringInfoChar(str, ')');
}
appendStringInfoChar(str, ' ');
}
if (copy_stmt->query != NULL)
{
appendStringInfoChar(str, '(');
deparsePreparableStmt(str, copy_stmt->query);
appendStringInfoString(str, ") ");
}
if (copy_stmt->is_from)
appendStringInfoString(str, "FROM ");
else
appendStringInfoString(str, "TO ");
if (copy_stmt->is_program)
appendStringInfoString(str, "PROGRAM ");
if (copy_stmt->filename != NULL)
{
deparseStringLiteral(str, copy_stmt->filename);
appendStringInfoChar(str, ' ');
}
else
{
if (copy_stmt->is_from)
appendStringInfoString(str, "STDIN ");
else
appendStringInfoString(str, "STDOUT ");
}
if (list_length(copy_stmt->options) > 0)
{
bool old_fmt = true;
foreach(lc, copy_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
{}
else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
{}
else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
{}
else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
{}
else
{
old_fmt = false;
break;
}
}
if (old_fmt) {
foreach(lc, copy_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
{
appendStringInfoString(str, "FREEZE ");
}
else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
{
appendStringInfoString(str, "HEADER ");
}
else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
{
appendStringInfoString(str, "CSV ");
}
else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
{
appendStringInfoString(str, "FORCE QUOTE ");
deparseColumnList(str, castNode(List, def_elem->arg));
}
else
{
Assert(false);
}
}
} else {
appendStringInfoString(str, "WITH (");
foreach(lc, copy_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "format") == 0)
{
appendStringInfoString(str, "FORMAT ");
char *format = strVal(def_elem->arg);
if (strcmp(format, "binary") == 0)
appendStringInfoString(str, "BINARY");
else if (strcmp(format, "csv") == 0)
appendStringInfoString(str, "CSV");
else if (strcmp(format, "text") == 0)
appendStringInfoString(str, "TEXT");
else
Assert(false);
}
else if (strcmp(def_elem->defname, "freeze") == 0)
{
appendStringInfoString(str, "FREEZE");
deparseOptBoolean(str, def_elem->arg);
}
else if (strcmp(def_elem->defname, "delimiter") == 0)
{
appendStringInfoString(str, "DELIMITER ");
deparseStringLiteral(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "null") == 0)
{
appendStringInfoString(str, "NULL ");
deparseStringLiteral(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "header") == 0)
{
appendStringInfoString(str, "HEADER");
deparseOptBoolean(str, def_elem->arg);
}
else if (strcmp(def_elem->defname, "quote") == 0)
{
appendStringInfoString(str, "QUOTE ");
deparseStringLiteral(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "escape") == 0)
{
appendStringInfoString(str, "ESCAPE ");
deparseStringLiteral(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "force_quote") == 0)
{
appendStringInfoString(str, "FORCE_QUOTE ");
if (IsA(def_elem->arg, A_Star))
{
appendStringInfoChar(str, '*');
}
else if (IsA(def_elem->arg, List))
{
appendStringInfoChar(str, '(');
deparseColumnList(str, castNode(List, def_elem->arg));
appendStringInfoChar(str, ')');
}
else
{
Assert(false);
}
}
else if (strcmp(def_elem->defname, "force_not_null") == 0)
{
appendStringInfoString(str, "FORCE_NOT_NULL ");
if (IsA(def_elem->arg, A_Star))
deparseAStar(str, castNode(A_Star, def_elem->arg));
else
{
appendStringInfoChar(str, '(');
deparseColumnList(str, castNode(List, def_elem->arg));
appendStringInfoChar(str, ')');
}
}
else if (strcmp(def_elem->defname, "force_null") == 0)
{
appendStringInfoString(str, "FORCE_NULL ");
if (IsA(def_elem->arg, A_Star))
deparseAStar(str, castNode(A_Star, def_elem->arg));
else
{
appendStringInfoChar(str, '(');
deparseColumnList(str, castNode(List, def_elem->arg));
appendStringInfoChar(str, ')');
}
}
else if (strcmp(def_elem->defname, "encoding") == 0)
{
appendStringInfoString(str, "ENCODING ");
deparseStringLiteral(str, strVal(def_elem->arg));
}
else
{
appendStringInfoString(str, quote_identifier(def_elem->defname));
if (def_elem->arg != NULL)
appendStringInfoChar(str, ' ');
if (def_elem->arg == NULL)
{
}
else if (IsA(def_elem->arg, String))
{
deparseOptBooleanOrString(str, strVal(def_elem->arg));
}
else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
{
deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
}
else if (IsA(def_elem->arg, A_Star))
{
deparseAStar(str, castNode(A_Star, def_elem->arg));
}
else if (IsA(def_elem->arg, List))
{
List *l = castNode(List, def_elem->arg);
appendStringInfoChar(str, '(');
foreach(lc2, l)
{
deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
if (lnext(l, lc2))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
}
if (lnext(copy_stmt->options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
}
deparseWhereClause(str, copy_stmt->whereClause);
removeTrailingSpace(str);
}
static void deparseDoStmt(StringInfo str, DoStmt *do_stmt)
{
ListCell *lc;
appendStringInfoString(str, "DO ");
foreach (lc, do_stmt->args)
{
DefElem *defel = castNode(DefElem, lfirst(lc));
if (strcmp(defel->defname, "language") == 0)
{
appendStringInfoString(str, "LANGUAGE ");
appendStringInfoString(str, quote_identifier(strVal(defel->arg)));
appendStringInfoChar(str, ' ');
}
else if (strcmp(defel->defname, "as") == 0)
{
char *strval = strVal(defel->arg);
const char *delim = "$$";
if (strstr(strval, "$$") != NULL)
delim = "$outer$";
appendStringInfoString(str, delim);
appendStringInfoString(str, strval);
appendStringInfoString(str, delim);
appendStringInfoChar(str, ' ');
}
}
removeTrailingSpace(str);
}
static void deparseDiscardStmt(StringInfo str, DiscardStmt *discard_stmt)
{
appendStringInfoString(str, "DISCARD ");
switch (discard_stmt->target)
{
case DISCARD_ALL:
appendStringInfoString(str, "ALL");
break;
case DISCARD_PLANS:
appendStringInfoString(str, "PLANS");
break;
case DISCARD_SEQUENCES:
appendStringInfoString(str, "SEQUENCES");
break;
case DISCARD_TEMP:
appendStringInfoString(str, "TEMP");
break;
}
}
static void deparseDefineStmt(StringInfo str, DefineStmt *define_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
if (define_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
switch (define_stmt->kind)
{
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
break;
case OBJECT_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
break;
case OBJECT_TSPARSER:
appendStringInfoString(str, "TEXT SEARCH PARSER ");
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
break;
case OBJECT_TSTEMPLATE:
appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
break;
default:
Assert(false);
break;
}
if (define_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
switch (define_stmt->kind)
{
case OBJECT_AGGREGATE:
deparseFuncName(str, define_stmt->defnames);
break;
case OBJECT_OPERATOR:
deparseAnyOperator(str, define_stmt->defnames);
break;
case OBJECT_TYPE:
case OBJECT_TSPARSER:
case OBJECT_TSDICTIONARY:
case OBJECT_TSTEMPLATE:
case OBJECT_TSCONFIGURATION:
case OBJECT_COLLATION:
deparseAnyName(str, define_stmt->defnames);
break;
default:
Assert(false);
}
appendStringInfoChar(str, ' ');
if (!define_stmt->oldstyle && define_stmt->kind == OBJECT_AGGREGATE)
{
deparseAggrArgs(str, define_stmt->args);
appendStringInfoChar(str, ' ');
}
if (define_stmt->kind == OBJECT_COLLATION &&
list_length(define_stmt->definition) == 1 &&
strcmp(castNode(DefElem, linitial(define_stmt->definition))->defname, "from") == 0)
{
appendStringInfoString(str, "FROM ");
deparseAnyName(str, castNode(List, castNode(DefElem, linitial(define_stmt->definition))->arg));
}
else if (list_length(define_stmt->definition) > 0)
{
deparseDefinition(str, define_stmt->definition);
}
removeTrailingSpace(str);
}
static void deparseCompositeTypeStmt(StringInfo str, CompositeTypeStmt *composite_type_stmt)
{
ListCell *lc;
RangeVar *typevar;
appendStringInfoString(str, "CREATE TYPE ");
deparseRangeVar(str, composite_type_stmt->typevar, DEPARSE_NODE_CONTEXT_CREATE_TYPE);
appendStringInfoString(str, " AS (");
foreach(lc, composite_type_stmt->coldeflist)
{
deparseColumnDef(str, castNode(ColumnDef, lfirst(lc)));
if (lnext(composite_type_stmt->coldeflist, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparseCreateEnumStmt(StringInfo str, CreateEnumStmt *create_enum_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE TYPE ");
deparseAnyName(str, create_enum_stmt->typeName);
appendStringInfoString(str, " AS ENUM (");
foreach(lc, create_enum_stmt->vals)
{
deparseStringLiteral(str, strVal(lfirst(lc)));
if (lnext(create_enum_stmt->vals, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparseCreateRangeStmt(StringInfo str, CreateRangeStmt *create_range_stmt)
{
appendStringInfoString(str, "CREATE TYPE ");
deparseAnyName(str, create_range_stmt->typeName);
appendStringInfoString(str, " AS RANGE ");
deparseDefinition(str, create_range_stmt->params);
}
static void deparseAlterEnumStmt(StringInfo str, AlterEnumStmt *alter_enum_stmt)
{
appendStringInfoString(str, "ALTER TYPE ");
deparseAnyName(str, alter_enum_stmt->typeName);
appendStringInfoChar(str, ' ');
if (alter_enum_stmt->oldVal == NULL)
{
appendStringInfoString(str, "ADD VALUE ");
if (alter_enum_stmt->skipIfNewValExists)
appendStringInfoString(str, "IF NOT EXISTS ");
deparseStringLiteral(str, alter_enum_stmt->newVal);
appendStringInfoChar(str, ' ');
if (alter_enum_stmt->newValNeighbor)
{
if (alter_enum_stmt->newValIsAfter)
appendStringInfoString(str, "AFTER ");
else
appendStringInfoString(str, "BEFORE ");
deparseStringLiteral(str, alter_enum_stmt->newValNeighbor);
}
}
else
{
appendStringInfoString(str, "RENAME VALUE ");
deparseStringLiteral(str, alter_enum_stmt->oldVal);
appendStringInfoString(str, " TO ");
deparseStringLiteral(str, alter_enum_stmt->newVal);
}
removeTrailingSpace(str);
}
static void deparseAlterExtensionStmt(StringInfo str, AlterExtensionStmt *alter_extension_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "ALTER EXTENSION ");
deparseColId(str, alter_extension_stmt->extname);
appendStringInfoString(str, " UPDATE ");
foreach (lc, alter_extension_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
if (strcmp(def_elem->defname, "new_version") == 0)
{
appendStringInfoString(str, "TO ");
deparseNonReservedWordOrSconst(str, strVal(def_elem->arg));
}
else
{
Assert(false);
}
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseAlterExtensionContentsStmt(StringInfo str, AlterExtensionContentsStmt *alter_extension_contents_stmt)
{
List *l = NULL;
appendStringInfoString(str, "ALTER EXTENSION ");
deparseColId(str, alter_extension_contents_stmt->extname);
appendStringInfoChar(str, ' ');
if (alter_extension_contents_stmt->action == 1)
appendStringInfoString(str, "ADD ");
else if (alter_extension_contents_stmt->action == -1)
appendStringInfoString(str, "DROP ");
else
Assert(false);
switch (alter_extension_contents_stmt->objtype)
{
case OBJECT_ACCESS_METHOD:
appendStringInfoString(str, "ACCESS METHOD ");
break;
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
break;
case OBJECT_CAST:
appendStringInfoString(str, "CAST ");
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
break;
case OBJECT_CONVERSION:
appendStringInfoString(str, "CONVERSION ");
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
break;
case OBJECT_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
break;
case OBJECT_OPCLASS:
appendStringInfoString(str, "OPERATOR CLASS ");
break;
case OBJECT_OPFAMILY:
appendStringInfoString(str, "OPERATOR FAMILY ");
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
break;
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, "EVENT TRIGGER ");
break;
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_TSPARSER:
appendStringInfoString(str, "TEXT SEARCH PARSER ");
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
break;
case OBJECT_TSTEMPLATE:
appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
break;
case OBJECT_FDW:
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
break;
case OBJECT_FOREIGN_SERVER:
appendStringInfoString(str, "SERVER ");
break;
case OBJECT_TRANSFORM:
appendStringInfoString(str, "TRANSFORM ");
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
break;
default:
Assert(false);
break;
}
switch (alter_extension_contents_stmt->objtype)
{
case OBJECT_COLLATION:
case OBJECT_CONVERSION:
case OBJECT_TABLE:
case OBJECT_TSPARSER:
case OBJECT_TSDICTIONARY:
case OBJECT_TSTEMPLATE:
case OBJECT_TSCONFIGURATION:
case OBJECT_SEQUENCE:
case OBJECT_VIEW:
case OBJECT_MATVIEW:
case OBJECT_FOREIGN_TABLE:
deparseAnyName(str, castNode(List, alter_extension_contents_stmt->object));
break;
case OBJECT_ACCESS_METHOD:
case OBJECT_LANGUAGE:
case OBJECT_SCHEMA:
case OBJECT_EVENT_TRIGGER:
case OBJECT_FDW:
case OBJECT_FOREIGN_SERVER:
deparseColId(str, strVal(alter_extension_contents_stmt->object));
break;
case OBJECT_AGGREGATE:
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
break;
case OBJECT_CAST:
l = castNode(List, alter_extension_contents_stmt->object);
Assert(list_length(l) == 2);
appendStringInfoChar(str, '(');
deparseTypeName(str, castNode(TypeName, linitial(l)));
appendStringInfoString(str, " AS ");
deparseTypeName(str, castNode(TypeName, lsecond(l)));
appendStringInfoChar(str, ')');
break;
case OBJECT_DOMAIN:
case OBJECT_TYPE:
deparseTypeName(str, castNode(TypeName, alter_extension_contents_stmt->object));
break;
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
case OBJECT_ROUTINE:
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
break;
case OBJECT_OPERATOR:
deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_extension_contents_stmt->object));
break;
case OBJECT_OPFAMILY:
case OBJECT_OPCLASS:
l = castNode(List, alter_extension_contents_stmt->object);
Assert(list_length(l) == 2);
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
deparseColId(str, strVal(linitial(l)));
break;
case OBJECT_TRANSFORM:
l = castNode(List, alter_extension_contents_stmt->object);
appendStringInfoString(str, "FOR ");
deparseTypeName(str, castNode(TypeName, linitial(l)));
appendStringInfoString(str, " LANGUAGE ");
deparseColId(str, strVal(lsecond(l)));
break;
default:
Assert(false);
break;
}
}
static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
{
ListCell *lc;
if (access_priv->priv_name != NULL)
{
if (strcmp(access_priv->priv_name, "select") == 0)
appendStringInfoString(str, "select");
else if (strcmp(access_priv->priv_name, "references") == 0)
appendStringInfoString(str, "references");
else if (strcmp(access_priv->priv_name, "create") == 0)
appendStringInfoString(str, "create");
else
appendStringInfoString(str, quote_identifier(access_priv->priv_name));
}
else
{
appendStringInfoString(str, "ALL");
}
appendStringInfoChar(str, ' ');
if (list_length(access_priv->cols) > 0)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, access_priv->cols);
appendStringInfoChar(str, ')');
}
removeTrailingSpace(str);
}
static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
{
ListCell *lc;
if (grant_stmt->is_grant)
appendStringInfoString(str, "GRANT ");
else
appendStringInfoString(str, "REVOKE ");
if (!grant_stmt->is_grant && grant_stmt->grant_option)
appendStringInfoString(str, "GRANT OPTION FOR ");
if (list_length(grant_stmt->privileges) > 0)
{
foreach(lc, grant_stmt->privileges)
{
deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
if (lnext(grant_stmt->privileges, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
}
else
{
appendStringInfoString(str, "ALL ");
}
appendStringInfoString(str, "ON ");
deparsePrivilegeTarget(str, grant_stmt->targtype, grant_stmt->objtype, grant_stmt->objects);
appendStringInfoChar(str, ' ');
if (grant_stmt->is_grant)
appendStringInfoString(str, "TO ");
else
appendStringInfoString(str, "FROM ");
foreach(lc, grant_stmt->grantees)
{
deparseRoleSpec(str, castNode(RoleSpec, lfirst(lc)));
if (lnext(grant_stmt->grantees, lc))
appendStringInfoChar(str, ',');
appendStringInfoChar(str, ' ');
}
if (grant_stmt->is_grant && grant_stmt->grant_option)
appendStringInfoString(str, "WITH GRANT OPTION ");
deparseOptDropBehavior(str, grant_stmt->behavior);
if (grant_stmt->grantor)
{
appendStringInfoString(str, "GRANTED BY ");
deparseRoleSpec(str, castNode(RoleSpec, grant_stmt->grantor));
}
removeTrailingSpace(str);
}
static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
{
ListCell *lc;
if (grant_role_stmt->is_grant)
appendStringInfoString(str, "GRANT ");
else
appendStringInfoString(str, "REVOKE ");
if (!grant_role_stmt->is_grant && list_length(grant_role_stmt->opt)) {
DefElem *defelem = castNode(DefElem, linitial(grant_role_stmt->opt));
Assert(!castNode(Boolean, defelem->arg)->boolval);
if (strcmp("admin", defelem->defname) == 0) {
appendStringInfoString(str, "ADMIN ");
} else if (strcmp("inherit", defelem->defname) == 0) {
appendStringInfoString(str, "INHERIT ");
} else if (strcmp("set", defelem->defname) == 0) {
appendStringInfoString(str, "SET ");
}
appendStringInfoString(str, "OPTION FOR ");
}
foreach(lc, grant_role_stmt->granted_roles)
{
deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
if (lnext(grant_role_stmt->granted_roles, lc))
appendStringInfoChar(str, ',');
appendStringInfoChar(str, ' ');
}
if (grant_role_stmt->is_grant)
appendStringInfoString(str, "TO ");
else
appendStringInfoString(str, "FROM ");
deparseRoleList(str, grant_role_stmt->grantee_roles);
appendStringInfoChar(str, ' ');
if (grant_role_stmt->is_grant) {
if (list_length(grant_role_stmt->opt) > 0) {
appendStringInfoString(str, "WITH ");
}
foreach(lc, grant_role_stmt->opt) {
DefElem *defelem = castNode(DefElem, lfirst(lc));
if (strcmp("admin", defelem->defname) == 0) {
appendStringInfoString(str, "ADMIN ");
appendStringInfoString(str, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
} else if (strcmp("inherit", defelem->defname) == 0) {
appendStringInfoString(str, "INHERIT ");
appendStringInfoString(str, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
} else if (strcmp("set", defelem->defname) == 0) {
appendStringInfoString(str, "SET ");
appendStringInfoString(str, castNode(Boolean, defelem->arg)->boolval ? "OPTION" : "FALSE");
}
if (lnext(grant_role_stmt->opt, lc)) {
appendStringInfoChar(str, ',');
}
appendStringInfoChar(str, ' ');
}
}
if (grant_role_stmt->grantor)
{
appendStringInfoString(str, "GRANTED BY ");
deparseRoleSpec(str, castNode(RoleSpec, grant_role_stmt->grantor));
}
if (grant_role_stmt->behavior == DROP_CASCADE) {
appendStringInfoString(str, "CASCADE ");
}
removeTrailingSpace(str);
}
static void deparseDropRoleStmt(StringInfo str, DropRoleStmt *drop_role_stmt)
{
ListCell *lc;
appendStringInfoString(str, "DROP ROLE ");
if (drop_role_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRoleList(str, drop_role_stmt->roles);
}
static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
if (index_stmt->unique)
appendStringInfoString(str, "UNIQUE ");
appendStringInfoString(str, "INDEX ");
if (index_stmt->concurrent)
appendStringInfoString(str, "CONCURRENTLY ");
if (index_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
if (index_stmt->idxname != NULL)
{
appendStringInfoString(str, quote_identifier(index_stmt->idxname));
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "ON ");
deparseRangeVar(str, index_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (index_stmt->accessMethod != NULL)
{
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(index_stmt->accessMethod));
appendStringInfoChar(str, ' ');
}
appendStringInfoChar(str, '(');
foreach (lc, index_stmt->indexParams)
{
deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
if (lnext(index_stmt->indexParams, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
if (list_length(index_stmt->indexIncludingParams) > 0)
{
appendStringInfoString(str, "INCLUDE (");
foreach (lc, index_stmt->indexIncludingParams)
{
deparseIndexElem(str, castNode(IndexElem, lfirst(lc)));
if (lnext(index_stmt->indexIncludingParams, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
if (index_stmt->nulls_not_distinct)
{
appendStringInfoString(str, "NULLS NOT DISTINCT ");
}
deparseOptWith(str, index_stmt->options);
if (index_stmt->tableSpace != NULL)
{
appendStringInfoString(str, "TABLESPACE ");
appendStringInfoString(str, quote_identifier(index_stmt->tableSpace));
appendStringInfoChar(str, ' ');
}
deparseWhereClause(str, index_stmt->whereClause);
removeTrailingSpace(str);
}
static void deparseAlterOpFamilyStmt(StringInfo str, AlterOpFamilyStmt *alter_op_family_stmt)
{
appendStringInfoString(str, "ALTER OPERATOR FAMILY ");
deparseAnyName(str, alter_op_family_stmt->opfamilyname);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(alter_op_family_stmt->amname));
appendStringInfoChar(str, ' ');
if (alter_op_family_stmt->isDrop)
appendStringInfoString(str, "DROP ");
else
appendStringInfoString(str, "ADD ");
deparseOpclassItemList(str, alter_op_family_stmt->items);
}
static void deparsePrepareStmt(StringInfo str, PrepareStmt *prepare_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "PREPARE ");
deparseColId(str, prepare_stmt->name);
if (list_length(prepare_stmt->argtypes) > 0)
{
appendStringInfoChar(str, '(');
deparseTypeList(str, prepare_stmt->argtypes);
appendStringInfoChar(str, ')');
}
appendStringInfoString(str, " AS ");
deparsePreparableStmt(str, prepare_stmt->query);
}
static void deparseExecuteStmt(StringInfo str, ExecuteStmt *execute_stmt)
{
ListCell *lc;
appendStringInfoString(str, "EXECUTE ");
appendStringInfoString(str, quote_identifier(execute_stmt->name));
if (list_length(execute_stmt->params) > 0)
{
appendStringInfoChar(str, '(');
deparseExprList(str, execute_stmt->params);
appendStringInfoChar(str, ')');
}
}
static void deparseDeallocateStmt(StringInfo str, DeallocateStmt *deallocate_stmt)
{
appendStringInfoString(str, "DEALLOCATE ");
if (deallocate_stmt->name != NULL)
appendStringInfoString(str, quote_identifier(deallocate_stmt->name));
else
appendStringInfoString(str, "ALL");
}
static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
{
if (strcmp(def_elem->defname, "password") == 0)
{
appendStringInfoString(str, "PASSWORD ");
if (def_elem->arg == NULL)
{
appendStringInfoString(str, "NULL");
}
else if (IsA(def_elem->arg, ParamRef))
{
deparseParamRef(str, castNode(ParamRef, def_elem->arg));
}
else if (IsA(def_elem->arg, String))
{
deparseStringLiteral(str, strVal(def_elem->arg));
}
else
{
Assert(false);
}
}
else if (strcmp(def_elem->defname, "connectionlimit") == 0)
{
appendStringInfo(str, "CONNECTION LIMIT %d", intVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "validUntil") == 0)
{
appendStringInfoString(str, "VALID UNTIL ");
deparseStringLiteral(str, strVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "superuser") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "SUPERUSER");
}
else if (strcmp(def_elem->defname, "superuser") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOSUPERUSER");
}
else if (strcmp(def_elem->defname, "createrole") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "CREATEROLE");
}
else if (strcmp(def_elem->defname, "createrole") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOCREATEROLE");
}
else if (strcmp(def_elem->defname, "isreplication") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "REPLICATION");
}
else if (strcmp(def_elem->defname, "isreplication") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOREPLICATION");
}
else if (strcmp(def_elem->defname, "createdb") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "CREATEDB");
}
else if (strcmp(def_elem->defname, "createdb") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOCREATEDB");
}
else if (strcmp(def_elem->defname, "canlogin") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "LOGIN");
}
else if (strcmp(def_elem->defname, "canlogin") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOLOGIN");
}
else if (strcmp(def_elem->defname, "bypassrls") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "BYPASSRLS");
}
else if (strcmp(def_elem->defname, "bypassrls") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOBYPASSRLS");
}
else if (strcmp(def_elem->defname, "inherit") == 0 && boolVal(def_elem->arg))
{
appendStringInfoString(str, "INHERIT");
}
else if (strcmp(def_elem->defname, "inherit") == 0 && !boolVal(def_elem->arg))
{
appendStringInfoString(str, "NOINHERIT");
}
else
{
Assert(false);
}
}
static void deparseCreateRoleElem(StringInfo str, DefElem *def_elem)
{
if (strcmp(def_elem->defname, "sysid") == 0)
{
appendStringInfo(str, "SYSID %d", intVal(def_elem->arg));
}
else if (strcmp(def_elem->defname, "adminmembers") == 0)
{
appendStringInfoString(str, "ADMIN ");
deparseRoleList(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "rolemembers") == 0)
{
appendStringInfoString(str, "ROLE ");
deparseRoleList(str, castNode(List, def_elem->arg));
}
else if (strcmp(def_elem->defname, "addroleto") == 0)
{
appendStringInfoString(str, "IN ROLE ");
deparseRoleList(str, castNode(List, def_elem->arg));
}
else
{
deparseAlterRoleElem(str, def_elem);
}
}
static void deparseCreatePLangStmt(StringInfo str, CreatePLangStmt *create_p_lang_stmt)
{
appendStringInfoString(str, "CREATE ");
if (create_p_lang_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
if (create_p_lang_stmt->pltrusted)
appendStringInfoString(str, "TRUSTED ");
appendStringInfoString(str, "LANGUAGE ");
deparseNonReservedWordOrSconst(str, create_p_lang_stmt->plname);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "HANDLER ");
deparseHandlerName(str, create_p_lang_stmt->plhandler);
appendStringInfoChar(str, ' ');
if (create_p_lang_stmt->plinline)
{
appendStringInfoString(str, "INLINE ");
deparseHandlerName(str, create_p_lang_stmt->plinline);
appendStringInfoChar(str, ' ');
}
if (create_p_lang_stmt->plvalidator)
{
appendStringInfoString(str, "VALIDATOR ");
deparseHandlerName(str, create_p_lang_stmt->plvalidator);
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseCreateRoleStmt(StringInfo str, CreateRoleStmt *create_role_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
switch (create_role_stmt->stmt_type)
{
case ROLESTMT_ROLE:
appendStringInfoString(str, "ROLE ");
break;
case ROLESTMT_USER:
appendStringInfoString(str, "USER ");
break;
case ROLESTMT_GROUP:
appendStringInfoString(str, "GROUP ");
break;
}
appendStringInfoString(str, quote_identifier(create_role_stmt->role));
appendStringInfoChar(str, ' ');
if (create_role_stmt->options != NULL)
{
appendStringInfoString(str, "WITH ");
foreach (lc, create_role_stmt->options)
{
deparseCreateRoleElem(str, castNode(DefElem, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
}
removeTrailingSpace(str);
}
static void deparseAlterRoleStmt(StringInfo str, AlterRoleStmt *alter_role_stmt)
{
ListCell *lc;
appendStringInfoString(str, "ALTER ");
if (list_length(alter_role_stmt->options) == 1 && strcmp(castNode(DefElem, linitial(alter_role_stmt->options))->defname, "rolemembers") == 0)
{
appendStringInfoString(str, "GROUP ");
deparseRoleSpec(str, alter_role_stmt->role);
appendStringInfoChar(str, ' ');
if (alter_role_stmt->action == 1)
{
appendStringInfoString(str, "ADD USER ");
}
else if (alter_role_stmt->action == -1)
{
appendStringInfoString(str, "DROP USER ");
}
else
{
Assert(false);
}
deparseRoleList(str, castNode(List, castNode(DefElem, linitial(alter_role_stmt->options))->arg));
}
else
{
appendStringInfoString(str, "ROLE ");
deparseRoleSpec(str, alter_role_stmt->role);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "WITH ");
foreach (lc, alter_role_stmt->options)
{
deparseAlterRoleElem(str, castNode(DefElem, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
}
removeTrailingSpace(str);
}
static void deparseDeclareCursorStmt(StringInfo str, DeclareCursorStmt *declare_cursor_stmt)
{
appendStringInfoString(str, "DECLARE ");
appendStringInfoString(str, quote_identifier(declare_cursor_stmt->portalname));
appendStringInfoChar(str, ' ');
if (declare_cursor_stmt->options & CURSOR_OPT_BINARY)
appendStringInfoString(str, "BINARY ");
if (declare_cursor_stmt->options & CURSOR_OPT_SCROLL)
appendStringInfoString(str, "SCROLL ");
if (declare_cursor_stmt->options & CURSOR_OPT_NO_SCROLL)
appendStringInfoString(str, "NO SCROLL ");
if (declare_cursor_stmt->options & CURSOR_OPT_INSENSITIVE)
appendStringInfoString(str, "INSENSITIVE ");
appendStringInfoString(str, "CURSOR ");
if (declare_cursor_stmt->options & CURSOR_OPT_HOLD)
appendStringInfoString(str, "WITH HOLD ");
appendStringInfoString(str, "FOR ");
deparseSelectStmt(str, castNode(SelectStmt, declare_cursor_stmt->query));
}
static void deparseFetchStmt(StringInfo str, FetchStmt *fetch_stmt)
{
if (fetch_stmt->ismove)
appendStringInfoString(str, "MOVE ");
else
appendStringInfoString(str, "FETCH ");
switch (fetch_stmt->direction)
{
case FETCH_FORWARD:
if (fetch_stmt->howMany == 1)
{
}
else if (fetch_stmt->howMany == FETCH_ALL)
{
appendStringInfoString(str, "ALL ");
}
else
{
appendStringInfo(str, "FORWARD %ld ", fetch_stmt->howMany);
}
break;
case FETCH_BACKWARD:
if (fetch_stmt->howMany == 1)
{
appendStringInfoString(str, "PRIOR ");
}
else if (fetch_stmt->howMany == FETCH_ALL)
{
appendStringInfoString(str, "BACKWARD ALL ");
}
else
{
appendStringInfo(str, "BACKWARD %ld ", fetch_stmt->howMany);
}
break;
case FETCH_ABSOLUTE:
if (fetch_stmt->howMany == 1)
{
appendStringInfoString(str, "FIRST ");
}
else if (fetch_stmt->howMany == -1)
{
appendStringInfoString(str, "LAST ");
}
else
{
appendStringInfo(str, "ABSOLUTE %ld ", fetch_stmt->howMany);
}
break;
case FETCH_RELATIVE:
appendStringInfo(str, "RELATIVE %ld ", fetch_stmt->howMany);
}
appendStringInfoString(str, quote_identifier(fetch_stmt->portalname));
}
static void deparseAlterDefaultPrivilegesStmt(StringInfo str, AlterDefaultPrivilegesStmt *alter_default_privileges_stmt)
{
ListCell *lc;
appendStringInfoString(str, "ALTER DEFAULT PRIVILEGES ");
foreach (lc, alter_default_privileges_stmt->options)
{
DefElem *defelem = castNode(DefElem, lfirst(lc));
if (strcmp(defelem->defname, "schemas") == 0)
{
appendStringInfoString(str, "IN SCHEMA ");
deparseNameList(str, castNode(List, defelem->arg));
appendStringInfoChar(str, ' ');
}
else if (strcmp(defelem->defname, "roles") == 0)
{
appendStringInfoString(str, "FOR ROLE ");
deparseRoleList(str, castNode(List, defelem->arg));
appendStringInfoChar(str, ' ');
}
else
{
Assert(false);
}
}
deparseGrantStmt(str, alter_default_privileges_stmt->action);
}
static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
{
appendStringInfoString(str, "REINDEX ");
deparseUtilityOptionList(str, reindex_stmt->params);
switch (reindex_stmt->kind)
{
case REINDEX_OBJECT_INDEX:
appendStringInfoString(str, "INDEX ");
break;
case REINDEX_OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case REINDEX_OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
break;
case REINDEX_OBJECT_SYSTEM:
appendStringInfoString(str, "SYSTEM ");
break;
case REINDEX_OBJECT_DATABASE:
appendStringInfoString(str, "DATABASE ");
break;
}
if (reindex_stmt->relation != NULL)
{
deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
}
else if (reindex_stmt->name != NULL)
{
appendStringInfoString(str, quote_identifier(reindex_stmt->name));
}
}
static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
if (rule_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
appendStringInfoString(str, "RULE ");
appendStringInfoString(str, quote_identifier(rule_stmt->rulename));
appendStringInfoString(str, " AS ON ");
switch (rule_stmt->event)
{
case CMD_UNKNOWN:
case CMD_UTILITY:
case CMD_NOTHING:
Assert(false);
break;
case CMD_SELECT:
appendStringInfoString(str, "SELECT ");
break;
case CMD_UPDATE:
appendStringInfoString(str, "UPDATE ");
break;
case CMD_INSERT:
appendStringInfoString(str, "INSERT ");
break;
case CMD_DELETE:
appendStringInfoString(str, "DELETE ");
break;
case CMD_MERGE:
appendStringInfoString(str, "MERGE ");
break;
}
appendStringInfoString(str, "TO ");
deparseRangeVar(str, rule_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
deparseWhereClause(str, rule_stmt->whereClause);
appendStringInfoString(str, "DO ");
if (rule_stmt->instead)
appendStringInfoString(str, "INSTEAD ");
if (list_length(rule_stmt->actions) == 0)
{
appendStringInfoString(str, "NOTHING");
}
else if (list_length(rule_stmt->actions) == 1)
{
deparseRuleActionStmt(str, linitial(rule_stmt->actions));
}
else
{
appendStringInfoChar(str, '(');
foreach (lc, rule_stmt->actions)
{
deparseRuleActionStmt(str, lfirst(lc));
if (lnext(rule_stmt->actions, lc))
appendStringInfoString(str, "; ");
}
appendStringInfoChar(str, ')');
}
}
static void deparseNotifyStmt(StringInfo str, NotifyStmt *notify_stmt)
{
appendStringInfoString(str, "NOTIFY ");
appendStringInfoString(str, quote_identifier(notify_stmt->conditionname));
if (notify_stmt->payload != NULL)
{
appendStringInfoString(str, ", ");
deparseStringLiteral(str, notify_stmt->payload);
}
}
static void deparseListenStmt(StringInfo str, ListenStmt *listen_stmt)
{
appendStringInfoString(str, "LISTEN ");
appendStringInfoString(str, quote_identifier(listen_stmt->conditionname));
}
static void deparseUnlistenStmt(StringInfo str, UnlistenStmt *unlisten_stmt)
{
appendStringInfoString(str, "UNLISTEN ");
if (unlisten_stmt->conditionname == NULL)
appendStringInfoString(str, "*");
else
appendStringInfoString(str, quote_identifier(unlisten_stmt->conditionname));
}
static void deparseCreateSeqStmt(StringInfo str, CreateSeqStmt *create_seq_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE ");
deparseOptTemp(str, create_seq_stmt->sequence->relpersistence);
appendStringInfoString(str, "SEQUENCE ");
if (create_seq_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
deparseRangeVar(str, create_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
deparseOptSeqOptList(str, create_seq_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterFunctionStmt(StringInfo str, AlterFunctionStmt *alter_function_stmt)
{
ListCell *lc;
appendStringInfoString(str, "ALTER ");
switch (alter_function_stmt->objtype)
{
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
break;
default:
Assert(false);
break;
}
deparseFunctionWithArgtypes(str, alter_function_stmt->func);
appendStringInfoChar(str, ' ');
foreach (lc, alter_function_stmt->actions)
{
deparseCommonFuncOptItem(str, castNode(DefElem, lfirst(lc)));
if (lnext(alter_function_stmt->actions, lc))
appendStringInfoChar(str, ' ');
}
}
static void deparseTruncateStmt(StringInfo str, TruncateStmt *truncate_stmt)
{
appendStringInfoString(str, "TRUNCATE ");
deparseRelationExprList(str, truncate_stmt->relations);
appendStringInfoChar(str, ' ');
if (truncate_stmt->restart_seqs)
appendStringInfoString(str, "RESTART IDENTITY ");
deparseOptDropBehavior(str, truncate_stmt->behavior);
removeTrailingSpace(str);
}
static void deparseCreateEventTrigStmt(StringInfo str, CreateEventTrigStmt *create_event_trig_stmt)
{
ListCell *lc = NULL;
ListCell *lc2 = NULL;
appendStringInfoString(str, "CREATE EVENT TRIGGER ");
appendStringInfoString(str, quote_identifier(create_event_trig_stmt->trigname));
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "ON ");
appendStringInfoString(str, quote_identifier(create_event_trig_stmt->eventname));
appendStringInfoChar(str, ' ');
if (create_event_trig_stmt->whenclause)
{
appendStringInfoString(str, "WHEN ");
foreach (lc, create_event_trig_stmt->whenclause)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
List *l = castNode(List, def_elem->arg);
appendStringInfoString(str, quote_identifier(def_elem->defname));
appendStringInfoString(str, " IN (");
foreach (lc2, l)
{
deparseStringLiteral(str, strVal(lfirst(lc2)));
if (lnext(l, lc2))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
if (lnext(create_event_trig_stmt->whenclause, lc))
appendStringInfoString(str, " AND ");
}
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "EXECUTE FUNCTION ");
deparseFuncName(str, create_event_trig_stmt->funcname);
appendStringInfoString(str, "()");
}
static void deparseAlterEventTrigStmt(StringInfo str, AlterEventTrigStmt *alter_event_trig_stmt)
{
appendStringInfoString(str, "ALTER EVENT TRIGGER ");
appendStringInfoString(str, quote_identifier(alter_event_trig_stmt->trigname));
appendStringInfoChar(str, ' ');
switch (alter_event_trig_stmt->tgenabled)
{
case TRIGGER_FIRES_ON_ORIGIN:
appendStringInfoString(str, "ENABLE");
break;
case TRIGGER_FIRES_ON_REPLICA:
appendStringInfoString(str, "ENABLE REPLICA");
break;
case TRIGGER_FIRES_ALWAYS:
appendStringInfoString(str, "ENABLE ALWAYS");
break;
case TRIGGER_DISABLED:
appendStringInfoString(str, "DISABLE");
break;
}
}
static void deparseRefreshMatViewStmt(StringInfo str, RefreshMatViewStmt *refresh_mat_view_stmt)
{
appendStringInfoString(str, "REFRESH MATERIALIZED VIEW ");
if (refresh_mat_view_stmt->concurrent)
appendStringInfoString(str, "CONCURRENTLY ");
deparseRangeVar(str, refresh_mat_view_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (refresh_mat_view_stmt->skipData)
appendStringInfoString(str, "WITH NO DATA ");
removeTrailingSpace(str);
}
static void deparseReplicaIdentityStmt(StringInfo str, ReplicaIdentityStmt *replica_identity_stmt)
{
switch (replica_identity_stmt->identity_type)
{
case REPLICA_IDENTITY_NOTHING:
appendStringInfoString(str, "NOTHING ");
break;
case REPLICA_IDENTITY_FULL:
appendStringInfoString(str, "FULL ");
break;
case REPLICA_IDENTITY_DEFAULT:
appendStringInfoString(str, "DEFAULT ");
break;
case REPLICA_IDENTITY_INDEX:
Assert(replica_identity_stmt->name != NULL);
appendStringInfoString(str, "USING INDEX ");
appendStringInfoString(str, quote_identifier(replica_identity_stmt->name));
break;
}
}
static void deparseCreatePolicyStmt(StringInfo str, CreatePolicyStmt *create_policy_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "CREATE POLICY ");
deparseColId(str, create_policy_stmt->policy_name);
appendStringInfoString(str, " ON ");
deparseRangeVar(str, create_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (!create_policy_stmt->permissive)
appendStringInfoString(str, "AS RESTRICTIVE ");
if (strcmp(create_policy_stmt->cmd_name, "all") == 0)
Assert(true); else if (strcmp(create_policy_stmt->cmd_name, "select") == 0)
appendStringInfoString(str, "FOR SELECT ");
else if (strcmp(create_policy_stmt->cmd_name, "insert") == 0)
appendStringInfoString(str, "FOR INSERT ");
else if (strcmp(create_policy_stmt->cmd_name, "update") == 0)
appendStringInfoString(str, "FOR UPDATE ");
else if (strcmp(create_policy_stmt->cmd_name, "delete") == 0)
appendStringInfoString(str, "FOR DELETE ");
else
Assert(false);
appendStringInfoString(str, "TO ");
deparseRoleList(str, create_policy_stmt->roles);
appendStringInfoChar(str, ' ');
if (create_policy_stmt->qual != NULL)
{
appendStringInfoString(str, "USING (");
deparseExpr(str, create_policy_stmt->qual, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
if (create_policy_stmt->with_check != NULL)
{
appendStringInfoString(str, "WITH CHECK (");
deparseExpr(str, create_policy_stmt->with_check, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
}
static void deparseAlterPolicyStmt(StringInfo str, AlterPolicyStmt *alter_policy_stmt)
{
appendStringInfoString(str, "ALTER POLICY ");
appendStringInfoString(str, quote_identifier(alter_policy_stmt->policy_name));
appendStringInfoString(str, " ON ");
deparseRangeVar(str, alter_policy_stmt->table, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (list_length(alter_policy_stmt->roles) > 0)
{
appendStringInfoString(str, "TO ");
deparseRoleList(str, alter_policy_stmt->roles);
appendStringInfoChar(str, ' ');
}
if (alter_policy_stmt->qual != NULL)
{
appendStringInfoString(str, "USING (");
deparseExpr(str, alter_policy_stmt->qual, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
if (alter_policy_stmt->with_check != NULL)
{
appendStringInfoString(str, "WITH CHECK (");
deparseExpr(str, alter_policy_stmt->with_check, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
}
static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *create_table_space_stmt)
{
appendStringInfoString(str, "CREATE TABLESPACE ");
deparseColId(str, create_table_space_stmt->tablespacename);
appendStringInfoChar(str, ' ');
if (create_table_space_stmt->owner != NULL)
{
appendStringInfoString(str, "OWNER ");
deparseRoleSpec(str, create_table_space_stmt->owner);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "LOCATION ");
if (create_table_space_stmt->location != NULL)
deparseStringLiteral(str, create_table_space_stmt->location);
else
appendStringInfoString(str, "''");
appendStringInfoChar(str, ' ');
deparseOptWith(str, create_table_space_stmt->options);
removeTrailingSpace(str);
}
static void deparseCreateTransformStmt(StringInfo str, CreateTransformStmt *create_transform_stmt)
{
appendStringInfoString(str, "CREATE ");
if (create_transform_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
appendStringInfoString(str, "TRANSFORM FOR ");
deparseTypeName(str, create_transform_stmt->type_name);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "LANGUAGE ");
appendStringInfoString(str, quote_identifier(create_transform_stmt->lang));
appendStringInfoChar(str, ' ');
appendStringInfoChar(str, '(');
if (create_transform_stmt->fromsql)
{
appendStringInfoString(str, "FROM SQL WITH FUNCTION ");
deparseFunctionWithArgtypes(str, create_transform_stmt->fromsql);
}
if (create_transform_stmt->fromsql && create_transform_stmt->tosql)
appendStringInfoString(str, ", ");
if (create_transform_stmt->tosql)
{
appendStringInfoString(str, "TO SQL WITH FUNCTION ");
deparseFunctionWithArgtypes(str, create_transform_stmt->tosql);
}
appendStringInfoChar(str, ')');
}
static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
{
appendStringInfoString(str, "CREATE ACCESS METHOD ");
appendStringInfoString(str, quote_identifier(create_am_stmt->amname));
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "TYPE ");
switch (create_am_stmt->amtype)
{
case AMTYPE_INDEX:
appendStringInfoString(str, "INDEX ");
break;
case AMTYPE_TABLE:
appendStringInfoString(str, "TABLE ");
break;
}
appendStringInfoString(str, "HANDLER ");
deparseHandlerName(str, create_am_stmt->handler_name);
}
static void deparsePublicationObjectList(StringInfo str, List *pubobjects) {
const ListCell *lc;
foreach(lc, pubobjects) {
PublicationObjSpec *obj = lfirst(lc);
switch (obj->pubobjtype) {
case PUBLICATIONOBJ_TABLE:
appendStringInfoString(str, "TABLE ");
deparseRangeVar(str, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
if (obj->pubtable->columns)
{
appendStringInfoChar(str, '(');
deparseColumnList(str, obj->pubtable->columns);
appendStringInfoChar(str, ')');
}
if (obj->pubtable->whereClause)
{
appendStringInfoString(str, " WHERE (");
deparseExpr(str, obj->pubtable->whereClause, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ")");
}
break;
case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
appendStringInfoString(str, "TABLES IN SCHEMA ");
appendStringInfoString(str, quote_identifier(obj->name));
break;
case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
appendStringInfoString(str, "TABLES IN SCHEMA CURRENT_SCHEMA");
break;
case PUBLICATIONOBJ_CONTINUATION:
Assert(false);
break;
}
if (lnext(pubobjects, lc)) {
appendStringInfoString(str, ", ");
}
}
}
static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "CREATE PUBLICATION ");
appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
appendStringInfoChar(str, ' ');
if (list_length(create_publication_stmt->pubobjects) > 0)
{
appendStringInfoString(str, "FOR ");
deparsePublicationObjectList(str, create_publication_stmt->pubobjects);
appendStringInfoChar(str, ' ');
}
else if (create_publication_stmt->for_all_tables)
{
appendStringInfoString(str, "FOR ALL TABLES ");
}
deparseOptDefinition(str, create_publication_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *alter_publication_stmt)
{
appendStringInfoString(str, "ALTER PUBLICATION ");
deparseColId(str, alter_publication_stmt->pubname);
appendStringInfoChar(str, ' ');
if (list_length(alter_publication_stmt->pubobjects) > 0)
{
switch (alter_publication_stmt->action)
{
case AP_SetObjects:
appendStringInfoString(str, "SET ");
break;
case AP_AddObjects:
appendStringInfoString(str, "ADD ");
break;
case AP_DropObjects:
appendStringInfoString(str, "DROP ");
break;
}
deparsePublicationObjectList(str, alter_publication_stmt->pubobjects);
}
else if (list_length(alter_publication_stmt->options) > 0)
{
appendStringInfoString(str, "SET ");
deparseDefinition(str, alter_publication_stmt->options);
}
else
{
Assert(false);
}
}
static void deparseAlterSeqStmt(StringInfo str, AlterSeqStmt *alter_seq_stmt)
{
ListCell *lc;
appendStringInfoString(str, "ALTER SEQUENCE ");
if (alter_seq_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseRangeVar(str, alter_seq_stmt->sequence, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
deparseSeqOptList(str, alter_seq_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterSystemStmt(StringInfo str, AlterSystemStmt *alter_system_stmt)
{
appendStringInfoString(str, "ALTER SYSTEM ");
deparseVariableSetStmt(str, alter_system_stmt->setstmt);
}
static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
{
ListCell *lc;
List *l;
appendStringInfoString(str, "COMMENT ON ");
switch (comment_stmt->objtype)
{
case OBJECT_COLUMN:
appendStringInfoString(str, "COLUMN ");
break;
case OBJECT_INDEX:
appendStringInfoString(str, "INDEX ");
break;
case OBJECT_SEQUENCE:
appendStringInfoString(str, "SEQUENCE ");
break;
case OBJECT_STATISTIC_EXT:
appendStringInfoString(str, "STATISTICS ");
break;
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_VIEW:
appendStringInfoString(str, "VIEW ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
break;
case OBJECT_CONVERSION:
appendStringInfoString(str, "CONVERSION ");
break;
case OBJECT_FOREIGN_TABLE:
appendStringInfoString(str, "FOREIGN TABLE ");
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
break;
case OBJECT_TSPARSER:
appendStringInfoString(str, "TEXT SEARCH PARSER ");
break;
case OBJECT_TSTEMPLATE:
appendStringInfoString(str, "TEXT SEARCH TEMPLATE ");
break;
case OBJECT_ACCESS_METHOD:
appendStringInfoString(str, "ACCESS METHOD ");
break;
case OBJECT_DATABASE:
appendStringInfoString(str, "DATABASE ");
break;
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, "EVENT TRIGGER ");
break;
case OBJECT_EXTENSION:
appendStringInfoString(str, "EXTENSION ");
break;
case OBJECT_FDW:
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
break;
case OBJECT_PUBLICATION:
appendStringInfoString(str, "PUBLICATION ");
break;
case OBJECT_ROLE:
appendStringInfoString(str, "ROLE ");
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
break;
case OBJECT_FOREIGN_SERVER:
appendStringInfoString(str, "SERVER ");
break;
case OBJECT_SUBSCRIPTION:
appendStringInfoString(str, "SUBSCRIPTION ");
break;
case OBJECT_TABLESPACE:
appendStringInfoString(str, "TABLESPACE ");
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
break;
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
break;
case OBJECT_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
break;
case OBJECT_TABCONSTRAINT:
appendStringInfoString(str, "CONSTRAINT ");
break;
case OBJECT_DOMCONSTRAINT:
appendStringInfoString(str, "CONSTRAINT ");
break;
case OBJECT_POLICY:
appendStringInfoString(str, "POLICY ");
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
break;
case OBJECT_RULE:
appendStringInfoString(str, "RULE ");
break;
case OBJECT_TRANSFORM:
appendStringInfoString(str, "TRANSFORM ");
break;
case OBJECT_TRIGGER:
appendStringInfoString(str, "TRIGGER ");
break;
case OBJECT_OPCLASS:
appendStringInfoString(str, "OPERATOR CLASS ");
break;
case OBJECT_OPFAMILY:
appendStringInfoString(str, "OPERATOR FAMILY ");
break;
case OBJECT_LARGEOBJECT:
appendStringInfoString(str, "LARGE OBJECT ");
break;
case OBJECT_CAST:
appendStringInfoString(str, "CAST ");
break;
default:
Assert(false);
break;
}
switch (comment_stmt->objtype)
{
case OBJECT_COLUMN:
case OBJECT_INDEX:
case OBJECT_SEQUENCE:
case OBJECT_STATISTIC_EXT:
case OBJECT_TABLE:
case OBJECT_VIEW:
case OBJECT_MATVIEW:
case OBJECT_COLLATION:
case OBJECT_CONVERSION:
case OBJECT_FOREIGN_TABLE:
case OBJECT_TSCONFIGURATION:
case OBJECT_TSDICTIONARY:
case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
deparseAnyName(str, castNode(List, comment_stmt->object));
break;
case OBJECT_ACCESS_METHOD:
case OBJECT_DATABASE:
case OBJECT_EVENT_TRIGGER:
case OBJECT_EXTENSION:
case OBJECT_FDW:
case OBJECT_LANGUAGE:
case OBJECT_PUBLICATION:
case OBJECT_ROLE:
case OBJECT_SCHEMA:
case OBJECT_FOREIGN_SERVER:
case OBJECT_SUBSCRIPTION:
case OBJECT_TABLESPACE:
appendStringInfoString(str, quote_identifier(strVal(comment_stmt->object)));
break;
case OBJECT_TYPE:
case OBJECT_DOMAIN:
deparseTypeName(str, castNode(TypeName, comment_stmt->object));
break;
case OBJECT_AGGREGATE:
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
break;
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
case OBJECT_ROUTINE:
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
break;
case OBJECT_OPERATOR:
deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, comment_stmt->object));
break;
case OBJECT_TABCONSTRAINT:
case OBJECT_POLICY:
case OBJECT_RULE:
case OBJECT_TRIGGER:
l = castNode(List, comment_stmt->object);
appendStringInfoString(str, quote_identifier(strVal(llast(l))));
appendStringInfoString(str, " ON ");
deparseAnyNameSkipLast(str, l);
break;
case OBJECT_DOMCONSTRAINT:
l = castNode(List, comment_stmt->object);
appendStringInfoString(str, quote_identifier(strVal(llast(l))));
appendStringInfoString(str, " ON DOMAIN ");
deparseTypeName(str, linitial(l));
break;
case OBJECT_TRANSFORM:
l = castNode(List, comment_stmt->object);
appendStringInfoString(str, "FOR ");
deparseTypeName(str, castNode(TypeName, linitial(l)));
appendStringInfoString(str, " LANGUAGE ");
appendStringInfoString(str, quote_identifier(strVal(lsecond(l))));
break;
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
l = castNode(List, comment_stmt->object);
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
break;
case OBJECT_LARGEOBJECT:
deparseValue(str, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
break;
case OBJECT_CAST:
l = castNode(List, comment_stmt->object);
appendStringInfoChar(str, '(');
deparseTypeName(str, castNode(TypeName, linitial(l)));
appendStringInfoString(str, " AS ");
deparseTypeName(str, castNode(TypeName, lsecond(l)));
appendStringInfoChar(str, ')');
break;
default:
Assert(false);
break;
}
appendStringInfoString(str, " IS ");
if (comment_stmt->comment != NULL)
deparseStringLiteral(str, comment_stmt->comment);
else
appendStringInfoString(str, "NULL");
}
static void deparseStatsElem(StringInfo str, StatsElem *stats_elem)
{
if (stats_elem->name)
appendStringInfoString(str, stats_elem->name);
else if (stats_elem->expr)
{
appendStringInfoChar(str, '(');
deparseExpr(str, stats_elem->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
}
}
static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE STATISTICS ");
if (create_stats_stmt->if_not_exists)
appendStringInfoString(str, "IF NOT EXISTS ");
deparseAnyName(str, create_stats_stmt->defnames);
appendStringInfoChar(str, ' ');
if (list_length(create_stats_stmt->stat_types) > 0)
{
appendStringInfoChar(str, '(');
deparseNameList(str, create_stats_stmt->stat_types);
appendStringInfoString(str, ") ");
}
appendStringInfoString(str, "ON ");
foreach (lc, create_stats_stmt->exprs)
{
deparseStatsElem(str, lfirst(lc));
if (lnext(create_stats_stmt->exprs, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, " FROM ");
deparseFromList(str, create_stats_stmt->relations);
}
static void deparseAlterCollationStmt(StringInfo str, AlterCollationStmt *alter_collation_stmt)
{
appendStringInfoString(str, "ALTER COLLATION ");
deparseAnyName(str, alter_collation_stmt->collname);
appendStringInfoString(str, " REFRESH VERSION");
}
static void deparseAlterDatabaseStmt(StringInfo str, AlterDatabaseStmt *alter_database_stmt)
{
appendStringInfoString(str, "ALTER DATABASE ");
deparseColId(str, alter_database_stmt->dbname);
appendStringInfoChar(str, ' ');
deparseCreatedbOptList(str, alter_database_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterDatabaseSetStmt(StringInfo str, AlterDatabaseSetStmt *alter_database_set_stmt)
{
appendStringInfoString(str, "ALTER DATABASE ");
deparseColId(str, alter_database_set_stmt->dbname);
appendStringInfoChar(str, ' ');
deparseVariableSetStmt(str, alter_database_set_stmt->setstmt);
}
static void deparseAlterStatsStmt(StringInfo str, AlterStatsStmt *alter_stats_stmt)
{
appendStringInfoString(str, "ALTER STATISTICS ");
if (alter_stats_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
deparseAnyName(str, alter_stats_stmt->defnames);
appendStringInfoChar(str, ' ');
if (alter_stats_stmt->stxstattarget)
appendStringInfo(str, "SET STATISTICS %d", castNode(Integer, alter_stats_stmt->stxstattarget)->ival);
else
appendStringInfo(str, "SET STATISTICS DEFAULT");
}
static void deparseAlterTSDictionaryStmt(StringInfo str, AlterTSDictionaryStmt *alter_ts_dictionary_stmt)
{
appendStringInfoString(str, "ALTER TEXT SEARCH DICTIONARY ");
deparseAnyName(str, alter_ts_dictionary_stmt->dictname);
appendStringInfoChar(str, ' ');
deparseDefinition(str, alter_ts_dictionary_stmt->options);
}
static void deparseAlterTSConfigurationStmt(StringInfo str, AlterTSConfigurationStmt *alter_ts_configuration_stmt)
{
ListCell *lc = NULL;
appendStringInfoString(str, "ALTER TEXT SEARCH CONFIGURATION ");
deparseAnyName(str, alter_ts_configuration_stmt->cfgname);
appendStringInfoChar(str, ' ');
switch (alter_ts_configuration_stmt->kind)
{
case ALTER_TSCONFIG_ADD_MAPPING:
appendStringInfoString(str, "ADD MAPPING FOR ");
deparseNameList(str, alter_ts_configuration_stmt->tokentype);
appendStringInfoString(str, " WITH ");
deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
break;
case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
appendStringInfoString(str, "ALTER MAPPING FOR ");
deparseNameList(str, alter_ts_configuration_stmt->tokentype);
appendStringInfoString(str, " WITH ");
deparseAnyNameList(str, alter_ts_configuration_stmt->dicts);
break;
case ALTER_TSCONFIG_REPLACE_DICT:
appendStringInfoString(str, "ALTER MAPPING REPLACE ");
deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
appendStringInfoString(str, " WITH ");
deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
break;
case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
appendStringInfoString(str, "ALTER MAPPING FOR ");
deparseNameList(str, alter_ts_configuration_stmt->tokentype);
appendStringInfoString(str, " REPLACE ");
deparseAnyName(str, linitial(alter_ts_configuration_stmt->dicts));
appendStringInfoString(str, " WITH ");
deparseAnyName(str, lsecond(alter_ts_configuration_stmt->dicts));
break;
case ALTER_TSCONFIG_DROP_MAPPING:
appendStringInfoString(str, "DROP MAPPING ");
if (alter_ts_configuration_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
appendStringInfoString(str, "FOR ");
deparseNameList(str, alter_ts_configuration_stmt->tokentype);
break;
}
}
static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_show_stmt)
{
appendStringInfoString(str, "SHOW ");
if (strcmp(variable_show_stmt->name, "timezone") == 0)
appendStringInfoString(str, "TIME ZONE");
else if (strcmp(variable_show_stmt->name, "transaction_isolation") == 0)
appendStringInfoString(str, "TRANSACTION ISOLATION LEVEL");
else if (strcmp(variable_show_stmt->name, "session_authorization") == 0)
appendStringInfoString(str, "SESSION AUTHORIZATION");
else if (strcmp(variable_show_stmt->name, "all") == 0)
appendStringInfoString(str, "ALL");
else
appendStringInfoString(str, quote_identifier(variable_show_stmt->name));
}
static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
{
deparseRangeVar(str, castNode(RangeVar, range_table_sample->relation), DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoString(str, " TABLESAMPLE ");
deparseFuncName(str, range_table_sample->method);
appendStringInfoChar(str, '(');
deparseExprList(str, range_table_sample->args);
appendStringInfoString(str, ") ");
if (range_table_sample->repeatable != NULL)
{
appendStringInfoString(str, "REPEATABLE (");
deparseExpr(str, range_table_sample->repeatable, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
removeTrailingSpace(str);
}
static void deparseCreateSubscriptionStmt(StringInfo str, CreateSubscriptionStmt *create_subscription_stmt)
{
ListCell *lc;
appendStringInfoString(str, "CREATE SUBSCRIPTION ");
appendStringInfoString(str, quote_identifier(create_subscription_stmt->subname));
appendStringInfoString(str, " CONNECTION ");
if (create_subscription_stmt->conninfo != NULL)
deparseStringLiteral(str, create_subscription_stmt->conninfo);
else
appendStringInfoString(str, "''");
appendStringInfoString(str, " PUBLICATION ");
foreach(lc, create_subscription_stmt->publication)
{
deparseColLabel(str, strVal(lfirst(lc)));
if (lnext(create_subscription_stmt->publication, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
deparseOptDefinition(str, create_subscription_stmt->options);
removeTrailingSpace(str);
}
static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *alter_subscription_stmt)
{
ListCell *lc;
appendStringInfoString(str, "ALTER SUBSCRIPTION ");
appendStringInfoString(str, quote_identifier(alter_subscription_stmt->subname));
appendStringInfoChar(str, ' ');
switch (alter_subscription_stmt->kind)
{
case ALTER_SUBSCRIPTION_OPTIONS:
appendStringInfoString(str, "SET ");
deparseDefinition(str, alter_subscription_stmt->options);
break;
case ALTER_SUBSCRIPTION_SKIP:
appendStringInfoString(str, "SKIP ");
deparseDefinition(str, alter_subscription_stmt->options);
break;
case ALTER_SUBSCRIPTION_CONNECTION:
appendStringInfoString(str, "CONNECTION ");
deparseStringLiteral(str, alter_subscription_stmt->conninfo);
appendStringInfoChar(str, ' ');
break;
case ALTER_SUBSCRIPTION_REFRESH:
appendStringInfoString(str, "REFRESH PUBLICATION ");
deparseOptDefinition(str, alter_subscription_stmt->options);
break;
case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
appendStringInfoString(str, "ADD PUBLICATION ");
foreach(lc, alter_subscription_stmt->publication)
{
deparseColLabel(str, strVal(lfirst(lc)));
if (lnext(alter_subscription_stmt->publication, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
deparseOptDefinition(str, alter_subscription_stmt->options);
break;
case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
appendStringInfoString(str, "DROP PUBLICATION ");
foreach(lc, alter_subscription_stmt->publication)
{
deparseColLabel(str, strVal(lfirst(lc)));
if (lnext(alter_subscription_stmt->publication, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
deparseOptDefinition(str, alter_subscription_stmt->options);
break;
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
appendStringInfoString(str, "SET PUBLICATION ");
foreach(lc, alter_subscription_stmt->publication)
{
deparseColLabel(str, strVal(lfirst(lc)));
if (lnext(alter_subscription_stmt->publication, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
deparseOptDefinition(str, alter_subscription_stmt->options);
break;
case ALTER_SUBSCRIPTION_ENABLED:
Assert(list_length(alter_subscription_stmt->options) == 1);
DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
Assert(strcmp(defelem->defname, "enabled") == 0);
if (optBooleanValue(defelem->arg))
{
appendStringInfoString(str, " ENABLE ");
}
else
{
appendStringInfoString(str, " DISABLE ");
}
break;
}
removeTrailingSpace(str);
}
static void deparseDropSubscriptionStmt(StringInfo str, DropSubscriptionStmt *drop_subscription_stmt)
{
appendStringInfoString(str, "DROP SUBSCRIPTION ");
if (drop_subscription_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
appendStringInfoString(str, drop_subscription_stmt->subname);
}
static void deparseCallStmt(StringInfo str, CallStmt *call_stmt)
{
appendStringInfoString(str, "CALL ");
deparseFuncCall(str, call_stmt->funccall, DEPARSE_NODE_CONTEXT_NONE);
}
static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_stmt)
{
List *l = NULL;
appendStringInfoString(str, "ALTER ");
switch (alter_owner_stmt->objectType)
{
case OBJECT_AGGREGATE:
appendStringInfoString(str, "AGGREGATE ");
deparseAggregateWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
break;
case OBJECT_COLLATION:
appendStringInfoString(str, "COLLATION ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_CONVERSION:
appendStringInfoString(str, "CONVERSION ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_DATABASE:
appendStringInfoString(str, "DATABASE ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_DOMAIN:
appendStringInfoString(str, "DOMAIN ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_FUNCTION:
appendStringInfoString(str, "FUNCTION ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
break;
case OBJECT_LANGUAGE:
appendStringInfoString(str, "LANGUAGE ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_LARGEOBJECT:
appendStringInfoString(str, "LARGE OBJECT ");
deparseNumericOnly(str, (union ValUnion *) alter_owner_stmt->object);
break;
case OBJECT_OPERATOR:
appendStringInfoString(str, "OPERATOR ");
deparseOperatorWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
break;
case OBJECT_OPCLASS:
l = castNode(List, alter_owner_stmt->object);
appendStringInfoString(str, "OPERATOR CLASS ");
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
deparseColId(str, strVal(linitial(l)));
break;
case OBJECT_OPFAMILY:
l = castNode(List, alter_owner_stmt->object);
appendStringInfoString(str, "OPERATOR FAMILY ");
deparseAnyNameSkipFirst(str, l);
appendStringInfoString(str, " USING ");
deparseColId(str, strVal(linitial(l)));
break;
case OBJECT_PROCEDURE:
appendStringInfoString(str, "PROCEDURE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
break;
case OBJECT_ROUTINE:
appendStringInfoString(str, "ROUTINE ");
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, alter_owner_stmt->object));
break;
case OBJECT_SCHEMA:
appendStringInfoString(str, "SCHEMA ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_TYPE:
appendStringInfoString(str, "TYPE ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_TABLESPACE:
appendStringInfoString(str, "TABLESPACE ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_STATISTIC_EXT:
appendStringInfoString(str, "STATISTICS ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_TSDICTIONARY:
appendStringInfoString(str, "TEXT SEARCH DICTIONARY ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_TSCONFIGURATION:
appendStringInfoString(str, "TEXT SEARCH CONFIGURATION ");
deparseAnyName(str, castNode(List, alter_owner_stmt->object));
break;
case OBJECT_FDW:
appendStringInfoString(str, "FOREIGN DATA WRAPPER ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_FOREIGN_SERVER:
appendStringInfoString(str, "SERVER ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_EVENT_TRIGGER:
appendStringInfoString(str, "EVENT TRIGGER ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_PUBLICATION:
appendStringInfoString(str, "PUBLICATION ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
case OBJECT_SUBSCRIPTION:
appendStringInfoString(str, "SUBSCRIPTION ");
deparseColId(str, strVal(alter_owner_stmt->object));
break;
default:
Assert(false);
}
appendStringInfoString(str, " OWNER TO ");
deparseRoleSpec(str, alter_owner_stmt->newowner);
}
static void deparseOperatorDefList(StringInfo str, List *defs)
{
ListCell *lc = NULL;
foreach (lc, defs)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
appendStringInfoString(str, quote_identifier(def_elem->defname));
appendStringInfoString(str, " = ");
if (def_elem->arg != NULL)
deparseDefArg(str, def_elem->arg, true);
else
appendStringInfoString(str, "NONE");
if (lnext(defs, lc))
appendStringInfoString(str, ", ");
}
}
static void deparseAlterOperatorStmt(StringInfo str, AlterOperatorStmt *alter_operator_stmt)
{
appendStringInfoString(str, "ALTER OPERATOR ");
deparseOperatorWithArgtypes(str, alter_operator_stmt->opername);
appendStringInfoString(str, " SET (");
deparseOperatorDefList(str, alter_operator_stmt->options);
appendStringInfoChar(str, ')');
}
static void deparseAlterTypeStmt(StringInfo str, AlterTypeStmt *alter_type_stmt)
{
appendStringInfoString(str, "ALTER TYPE ");
deparseAnyName(str, alter_type_stmt->typeName);
appendStringInfoString(str, " SET (");
deparseOperatorDefList(str, alter_type_stmt->options);
appendStringInfoChar(str, ')');
}
static void deparseDropOwnedStmt(StringInfo str, DropOwnedStmt *drop_owned_stmt)
{
appendStringInfoString(str, "DROP OWNED BY ");
deparseRoleList(str, drop_owned_stmt->roles);
appendStringInfoChar(str, ' ');
deparseOptDropBehavior(str, drop_owned_stmt->behavior);
removeTrailingSpace(str);
}
static void deparseReassignOwnedStmt(StringInfo str, ReassignOwnedStmt *reassigned_owned_stmt)
{
appendStringInfoString(str, "REASSIGN OWNED BY ");
deparseRoleList(str, reassigned_owned_stmt->roles);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, "TO ");
deparseRoleSpec(str, reassigned_owned_stmt->newrole);
}
static void deparseClosePortalStmt(StringInfo str, ClosePortalStmt *close_portal_stmt)
{
appendStringInfoString(str, "CLOSE ");
if (close_portal_stmt->portalname != NULL)
{
appendStringInfoString(str, quote_identifier(close_portal_stmt->portalname));
}
else
{
appendStringInfoString(str, "ALL");
}
}
static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
{
ListCell *lc;
bool skip_events_or = true;
appendStringInfoString(str, "CREATE ");
if (create_trig_stmt->replace)
appendStringInfoString(str, "OR REPLACE ");
if (create_trig_stmt->isconstraint)
appendStringInfoString(str, "CONSTRAINT ");
appendStringInfoString(str, "TRIGGER ");
appendStringInfoString(str, quote_identifier(create_trig_stmt->trigname));
appendStringInfoChar(str, ' ');
switch (create_trig_stmt->timing)
{
case TRIGGER_TYPE_BEFORE:
appendStringInfoString(str, "BEFORE ");
break;
case TRIGGER_TYPE_AFTER:
appendStringInfoString(str, "AFTER ");
break;
case TRIGGER_TYPE_INSTEAD:
appendStringInfoString(str, "INSTEAD OF ");
break;
default:
Assert(false);
}
if (TRIGGER_FOR_INSERT(create_trig_stmt->events))
{
appendStringInfoString(str, "INSERT ");
skip_events_or = false;
}
if (TRIGGER_FOR_DELETE(create_trig_stmt->events))
{
if (!skip_events_or)
appendStringInfoString(str, "OR ");
appendStringInfoString(str, "DELETE ");
skip_events_or = false;
}
if (TRIGGER_FOR_UPDATE(create_trig_stmt->events))
{
if (!skip_events_or)
appendStringInfoString(str, "OR ");
appendStringInfoString(str, "UPDATE ");
if (list_length(create_trig_stmt->columns) > 0)
{
appendStringInfoString(str, "OF ");
deparseColumnList(str, create_trig_stmt->columns);
appendStringInfoChar(str, ' ');
}
skip_events_or = false;
}
if (TRIGGER_FOR_TRUNCATE(create_trig_stmt->events))
{
if (!skip_events_or)
appendStringInfoString(str, "OR ");
appendStringInfoString(str, "TRUNCATE ");
}
appendStringInfoString(str, "ON ");
deparseRangeVar(str, create_trig_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
if (create_trig_stmt->transitionRels != NULL)
{
appendStringInfoString(str, "REFERENCING ");
foreach(lc, create_trig_stmt->transitionRels)
{
deparseTriggerTransition(str, castNode(TriggerTransition, lfirst(lc)));
appendStringInfoChar(str, ' ');
}
}
if (create_trig_stmt->constrrel != NULL)
{
appendStringInfoString(str, "FROM ");
deparseRangeVar(str, create_trig_stmt->constrrel, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
}
if (create_trig_stmt->deferrable)
appendStringInfoString(str, "DEFERRABLE ");
if (create_trig_stmt->initdeferred)
appendStringInfoString(str, "INITIALLY DEFERRED ");
if (create_trig_stmt->row)
appendStringInfoString(str, "FOR EACH ROW ");
if (create_trig_stmt->whenClause)
{
appendStringInfoString(str, "WHEN (");
deparseExpr(str, create_trig_stmt->whenClause, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
appendStringInfoString(str, "EXECUTE FUNCTION ");
deparseFuncName(str, create_trig_stmt->funcname);
appendStringInfoChar(str, '(');
foreach(lc, create_trig_stmt->args)
{
deparseStringLiteral(str, strVal(lfirst(lc)));
if (lnext(create_trig_stmt->args, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparseTriggerTransition(StringInfo str, TriggerTransition *trigger_transition)
{
if (trigger_transition->isNew)
appendStringInfoString(str, "NEW ");
else
appendStringInfoString(str, "OLD ");
if (trigger_transition->isTable)
appendStringInfoString(str, "TABLE ");
else
appendStringInfoString(str, "ROW ");
appendStringInfoString(str, quote_identifier(trigger_transition->name));
}
static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr, DeparseNodeContext context)
{
switch (xml_expr->op)
{
case IS_XMLCONCAT:
appendStringInfoString(str, "xmlconcat(");
deparseExprList(str, xml_expr->args);
appendStringInfoChar(str, ')');
break;
case IS_XMLELEMENT:
appendStringInfoString(str, "xmlelement(name ");
appendStringInfoString(str, quote_identifier(xml_expr->name));
if (xml_expr->named_args != NULL)
{
appendStringInfoString(str, ", xmlattributes(");
deparseXmlAttributeList(str, xml_expr->named_args);
appendStringInfoString(str, ")");
}
if (xml_expr->args != NULL)
{
appendStringInfoString(str, ", ");
deparseExprList(str, xml_expr->args);
}
appendStringInfoString(str, ")");
break;
case IS_XMLFOREST:
appendStringInfoString(str, "xmlforest(");
deparseXmlAttributeList(str, xml_expr->named_args);
appendStringInfoChar(str, ')');
break;
case IS_XMLPARSE:
Assert(list_length(xml_expr->args) == 2);
appendStringInfoString(str, "xmlparse(");
switch (xml_expr->xmloption)
{
case XMLOPTION_DOCUMENT:
appendStringInfoString(str, "document ");
break;
case XMLOPTION_CONTENT:
appendStringInfoString(str, "content ");
break;
default:
Assert(false);
}
deparseExpr(str, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ')');
break;
case IS_XMLPI:
appendStringInfoString(str, "xmlpi(name ");
appendStringInfoString(str, quote_identifier(xml_expr->name));
if (xml_expr->args != NULL)
{
appendStringInfoString(str, ", ");
deparseExpr(str, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
}
appendStringInfoChar(str, ')');
break;
case IS_XMLROOT:
appendStringInfoString(str, "xmlroot(");
deparseExpr(str, linitial(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ", version ");
if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
appendStringInfoString(str, "NO VALUE");
else
deparseExpr(str, lsecond(xml_expr->args), DEPARSE_NODE_CONTEXT_A_EXPR);
if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_YES)
appendStringInfoString(str, ", STANDALONE YES");
else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO)
appendStringInfoString(str, ", STANDALONE NO");
else if (intVal(&castNode(A_Const, lthird(xml_expr->args))->val) == XML_STANDALONE_NO_VALUE)
appendStringInfoString(str, ", STANDALONE NO VALUE");
appendStringInfoChar(str, ')');
break;
case IS_XMLSERIALIZE:
Assert(false);
break;
case IS_DOCUMENT:
Assert(list_length(xml_expr->args) == 1);
deparseExpr(str, linitial(xml_expr->args), context);
appendStringInfoString(str, " IS DOCUMENT");
break;
}
}
static void deparseRangeTableFuncCol(StringInfo str, RangeTableFuncCol* range_table_func_col)
{
appendStringInfoString(str, quote_identifier(range_table_func_col->colname));
appendStringInfoChar(str, ' ');
if (range_table_func_col->for_ordinality)
{
appendStringInfoString(str, "FOR ORDINALITY ");
}
else
{
deparseTypeName(str, range_table_func_col->typeName);
appendStringInfoChar(str, ' ');
if (range_table_func_col->colexpr)
{
appendStringInfoString(str, "PATH ");
deparseExpr(str, range_table_func_col->colexpr, DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoChar(str, ' ');
}
if (range_table_func_col->coldefexpr)
{
appendStringInfoString(str, "DEFAULT ");
deparseExpr(str, range_table_func_col->coldefexpr, DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoChar(str, ' ');
}
if (range_table_func_col->is_not_null)
appendStringInfoString(str, "NOT NULL ");
}
removeTrailingSpace(str);
}
static void deparseRangeTableFunc(StringInfo str, RangeTableFunc* range_table_func)
{
ListCell *lc;
if (range_table_func->lateral)
appendStringInfoString(str, "LATERAL ");
appendStringInfoString(str, "xmltable(");
if (range_table_func->namespaces)
{
appendStringInfoString(str, "xmlnamespaces(");
deparseXmlNamespaceList(str, range_table_func->namespaces);
appendStringInfoString(str, "), ");
}
appendStringInfoChar(str, '(');
deparseExpr(str, range_table_func->rowexpr, DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoChar(str, ')');
appendStringInfoString(str, " PASSING ");
deparseExpr(str, range_table_func->docexpr, DEPARSE_NODE_CONTEXT_NONE );
appendStringInfoString(str, " COLUMNS ");
foreach(lc, range_table_func->columns)
{
deparseRangeTableFuncCol(str, castNode(RangeTableFuncCol, lfirst(lc)));
if (lnext(range_table_func->columns, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
if (range_table_func->alias)
{
appendStringInfoString(str, "AS ");
deparseAlias(str, range_table_func->alias);
}
removeTrailingSpace(str);
}
static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize)
{
appendStringInfoString(str, "xmlserialize(");
switch (xml_serialize->xmloption)
{
case XMLOPTION_DOCUMENT:
appendStringInfoString(str, "document ");
break;
case XMLOPTION_CONTENT:
appendStringInfoString(str, "content ");
break;
default:
Assert(false);
}
deparseExpr(str, xml_serialize->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, " AS ");
deparseTypeName(str, xml_serialize->typeName);
if (xml_serialize->indent) {
appendStringInfoString(str, " INDENT");
}
appendStringInfoString(str, ")");
}
static void deparseJsonFormat(StringInfo str, JsonFormat *json_format)
{
if (json_format == NULL || json_format->format_type == JS_FORMAT_DEFAULT)
return;
appendStringInfoString(str, "FORMAT JSON ");
switch (json_format->encoding)
{
case JS_ENC_UTF8:
appendStringInfoString(str, "ENCODING utf8 ");
break;
case JS_ENC_UTF16:
appendStringInfoString(str, "ENCODING utf16 ");
break;
case JS_ENC_UTF32:
appendStringInfoString(str, "ENCODING utf32 ");
break;
case JS_ENC_DEFAULT:
break;
}
}
static void deparseJsonIsPredicate(StringInfo str, JsonIsPredicate *j)
{
deparseExpr(str, j->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
deparseJsonFormat(str, castNode(JsonFormat, j->format));
appendStringInfoString(str, "IS ");
switch (j->item_type)
{
case JS_TYPE_ANY:
appendStringInfoString(str, "JSON ");
break;
case JS_TYPE_ARRAY:
appendStringInfoString(str, "JSON ARRAY ");
break;
case JS_TYPE_OBJECT:
appendStringInfoString(str, "JSON OBJECT ");
break;
case JS_TYPE_SCALAR:
appendStringInfoString(str, "JSON SCALAR ");
break;
}
if (j->unique_keys)
appendStringInfoString(str, "WITH UNIQUE ");
removeTrailingSpace(str);
}
static void deparseJsonValueExpr(StringInfo str, JsonValueExpr *json_value_expr)
{
deparseExpr(str, (Node *) json_value_expr->raw_expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoChar(str, ' ');
deparseJsonFormat(str, json_value_expr->format);
}
static void deparseJsonValueExprList(StringInfo str, List *exprs)
{
ListCell *lc;
foreach(lc, exprs)
{
deparseJsonValueExpr(str, lfirst(lc));
removeTrailingSpace(str);
if (lnext(exprs, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
}
static void deparseJsonKeyValue(StringInfo str, JsonKeyValue *json_key_value)
{
deparseExpr(str, (Node *) json_key_value->key, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ": ");
deparseJsonValueExpr(str, json_key_value->value);
}
static void deparseJsonKeyValueList(StringInfo str, List *exprs)
{
ListCell *lc;
foreach(lc, exprs)
{
deparseJsonKeyValue(str, lfirst(lc));
removeTrailingSpace(str);
if (lnext(exprs, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
}
static void deparseJsonOutput(StringInfo str, JsonOutput *json_output)
{
if (json_output == NULL)
return;
Assert(json_output->returning != NULL);
appendStringInfoString(str, "RETURNING ");
deparseTypeName(str, json_output->typeName);
appendStringInfoChar(str, ' ');
deparseJsonFormat(str, json_output->returning->format);
}
static void deparseJsonObjectAgg(StringInfo str, JsonObjectAgg *json_object_agg)
{
Assert(json_object_agg->constructor != NULL);
appendStringInfoString(str, "JSON_OBJECTAGG(");
deparseJsonKeyValue(str, json_object_agg->arg);
if (json_object_agg->absent_on_null)
appendStringInfoString(str, "ABSENT ON NULL ");
if (json_object_agg->unique)
appendStringInfoString(str, "WITH UNIQUE ");
deparseJsonOutput(str, json_object_agg->constructor->output);
removeTrailingSpace(str);
appendStringInfoString(str, ") ");
if (json_object_agg->constructor->agg_filter)
{
appendStringInfoString(str, "FILTER (WHERE ");
deparseExpr(str, json_object_agg->constructor->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
if (json_object_agg->constructor->over)
{
struct WindowDef *over = json_object_agg->constructor->over;
appendStringInfoString(str, "OVER ");
if (over->name)
appendStringInfoString(str, over->name);
else
deparseWindowDef(str, over);
}
removeTrailingSpace(str);
}
static void deparseJsonArrayAgg(StringInfo str, JsonArrayAgg *json_array_agg)
{
Assert(json_array_agg->constructor != NULL);
appendStringInfoString(str, "JSON_ARRAYAGG(");
deparseJsonValueExpr(str, json_array_agg->arg);
deparseOptSortClause(str, json_array_agg->constructor->agg_order);
if (!json_array_agg->absent_on_null)
appendStringInfoString(str, "NULL ON NULL ");
deparseJsonOutput(str, json_array_agg->constructor->output);
removeTrailingSpace(str);
appendStringInfoString(str, ") ");
if (json_array_agg->constructor->agg_filter)
{
appendStringInfoString(str, "FILTER (WHERE ");
deparseExpr(str, json_array_agg->constructor->agg_filter, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ") ");
}
if (json_array_agg->constructor->over)
{
struct WindowDef *over = json_array_agg->constructor->over;
appendStringInfoString(str, "OVER ");
if (over->name)
appendStringInfoString(str, over->name);
else
deparseWindowDef(str, over);
}
removeTrailingSpace(str);
}
static void deparseJsonObjectConstructor(StringInfo str, JsonObjectConstructor *json_object_constructor)
{
appendStringInfoString(str, "JSON_OBJECT(");
deparseJsonKeyValueList(str, json_object_constructor->exprs);
if (json_object_constructor->absent_on_null)
appendStringInfoString(str, "ABSENT ON NULL ");
if (json_object_constructor->unique)
appendStringInfoString(str, "WITH UNIQUE ");
deparseJsonOutput(str, json_object_constructor->output);
removeTrailingSpace(str);
appendStringInfoChar(str, ')');
}
static void deparseJsonArrayConstructor(StringInfo str, JsonArrayConstructor *json_array_constructor)
{
appendStringInfoString(str, "JSON_ARRAY(");
deparseJsonValueExprList(str, json_array_constructor->exprs);
if (!json_array_constructor->absent_on_null)
appendStringInfoString(str, "NULL ON NULL ");
deparseJsonOutput(str, json_array_constructor->output);
removeTrailingSpace(str);
appendStringInfoChar(str, ')');
}
static void deparseJsonArrayQueryConstructor(StringInfo str, JsonArrayQueryConstructor *json_array_query_constructor)
{
appendStringInfoString(str, "JSON_ARRAY(");
deparseSelectStmt(str, castNode(SelectStmt, json_array_query_constructor->query));
deparseJsonFormat(str, json_array_query_constructor->format);
deparseJsonOutput(str, json_array_query_constructor->output);
removeTrailingSpace(str);
appendStringInfoChar(str, ')');
}
static void deparseJsonParseExpr(StringInfo str, JsonParseExpr *json_parse_expr)
{
appendStringInfoString(str, "JSON(");
deparseJsonValueExpr(str, json_parse_expr->expr);
if (json_parse_expr->unique_keys)
appendStringInfoString(str, " WITH UNIQUE KEYS");
appendStringInfoString(str, ")");
}
static void deparseJsonScalarExpr(StringInfo str, JsonScalarExpr *json_scalar_expr)
{
appendStringInfoString(str, "JSON_SCALAR(");
deparseExpr(str, (Node*) json_scalar_expr->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
appendStringInfoString(str, ")");
}
static void deparseJsonSerializeExpr(StringInfo str, JsonSerializeExpr *json_serialize_expr)
{
appendStringInfoString(str, "JSON_SERIALIZE(");
deparseJsonValueExpr(str, json_serialize_expr->expr);
if (json_serialize_expr->output)
deparseJsonOutput(str, json_serialize_expr->output);
appendStringInfoString(str, ")");
}
static void deparseJsonQuotesClauseOpt(StringInfo str, JsonQuotes quotes)
{
switch (quotes)
{
case JS_QUOTES_UNSPEC:
break;
case JS_QUOTES_KEEP:
appendStringInfoString(str, " KEEP QUOTES");
break;
case JS_QUOTES_OMIT:
appendStringInfoString(str, " OMIT QUOTES");
break;
}
}
static void deparseJsonOnErrorClauseOpt(StringInfo str, JsonBehavior *behavior)
{
if (!behavior)
return;
appendStringInfoChar(str, ' ');
deparseJsonBehavior(str, behavior);
appendStringInfoString(str, " ON ERROR");
}
static void deparseJsonOnEmptyClauseOpt(StringInfo str, JsonBehavior *behavior)
{
if (behavior)
{
appendStringInfoChar(str, ' ');
deparseJsonBehavior(str, behavior);
appendStringInfoString(str, " ON EMPTY");
}
}
static void deparseJsonFuncExpr(StringInfo str, JsonFuncExpr *json_func_expr)
{
switch (json_func_expr->op)
{
case JSON_EXISTS_OP:
appendStringInfoString(str, "JSON_EXISTS(");
break;
case JSON_QUERY_OP:
appendStringInfoString(str, "JSON_QUERY(");
break;
case JSON_VALUE_OP:
appendStringInfoString(str, "JSON_VALUE(");
break;
case JSON_TABLE_OP:
appendStringInfoString(str, "JSON_TABLE(");
break;
}
deparseJsonValueExpr(str, json_func_expr->context_item);
appendStringInfoString(str, ", ");
deparseExpr(str, json_func_expr->pathspec, DEPARSE_NODE_CONTEXT_A_EXPR);
if (json_func_expr->passing)
appendStringInfoString(str, " PASSING ");
ListCell *lc = NULL;
foreach (lc, json_func_expr->passing)
{
JsonArgument *json_argument = castNode(JsonArgument, lfirst(lc));
deparseJsonValueExpr(str, json_argument->val);
appendStringInfoString(str, " AS ");
deparseColLabel(str, json_argument->name);
if (lnext(json_func_expr->passing, lc))
appendStringInfoString(str, ", ");
}
if (json_func_expr->output)
{
appendStringInfoChar(str, ' ');
deparseJsonOutput(str, json_func_expr->output);
}
switch (json_func_expr->wrapper)
{
case JSW_UNSPEC:
break;
case JSW_NONE:
appendStringInfoString(str, " WITHOUT WRAPPER");
break;
case JSW_CONDITIONAL:
appendStringInfoString(str, " WITH CONDITIONAL WRAPPER");
break;
case JSW_UNCONDITIONAL:
appendStringInfoString(str, " WITH UNCONDITIONAL WRAPPER");
break;
}
deparseJsonQuotesClauseOpt(str, json_func_expr->quotes);
deparseJsonOnEmptyClauseOpt(str, json_func_expr->on_empty);
deparseJsonOnErrorClauseOpt(str, json_func_expr->on_error);
appendStringInfoChar(str, ')');
}
static void deparseJsonTablePathSpec(StringInfo str, JsonTablePathSpec *json_table_path_spec)
{
deparseStringLiteral(str, castNode(A_Const, json_table_path_spec->string)->val.sval.sval);
if (json_table_path_spec->name)
{
appendStringInfoString(str, " AS ");
deparseColLabel(str, json_table_path_spec->name);
}
}
static void deparseJsonBehavior(StringInfo str, JsonBehavior *json_behavior)
{
switch (json_behavior->btype)
{
case JSON_BEHAVIOR_NULL:
appendStringInfoString(str, "NULL");
break;
case JSON_BEHAVIOR_ERROR:
appendStringInfoString(str, "ERROR");
break;
case JSON_BEHAVIOR_EMPTY:
appendStringInfoString(str, "EMPTY");
break;
case JSON_BEHAVIOR_TRUE:
appendStringInfoString(str, "TRUE");
break;
case JSON_BEHAVIOR_FALSE:
appendStringInfoString(str, "FALSE");
break;
case JSON_BEHAVIOR_EMPTY_ARRAY:
appendStringInfoString(str, "EMPTY ARRAY");
break;
case JSON_BEHAVIOR_EMPTY_OBJECT:
appendStringInfoString(str, "EMPTY OBJECT");
break;
case JSON_BEHAVIOR_DEFAULT:
appendStringInfoString(str, "DEFAULT ");
deparseExpr(str, (Node*) json_behavior->expr, DEPARSE_NODE_CONTEXT_A_EXPR);
break;
case JSON_BEHAVIOR_UNKNOWN:
appendStringInfoString(str, "UNKNOWN");
break;
}
}
static void deparseJsonTableColumn(StringInfo str, JsonTableColumn *json_table_column)
{
if (json_table_column->coltype == JTC_NESTED)
{
appendStringInfoString(str, "NESTED PATH ");
deparseJsonTablePathSpec(str, json_table_column->pathspec);
deparseJsonTableColumns(str, json_table_column->columns);
return;
}
deparseColLabel(str, json_table_column->name);
appendStringInfoChar(str, ' ');
switch (json_table_column->coltype)
{
case JTC_FOR_ORDINALITY:
appendStringInfoString(str, " FOR ORDINALITY");
break;
case JTC_EXISTS:
case JTC_FORMATTED:
case JTC_REGULAR:
deparseTypeName(str, json_table_column->typeName);
if (json_table_column->coltype == JTC_EXISTS)
appendStringInfoString(str, " EXISTS ");
else
appendStringInfoChar(str, ' ');
if (json_table_column->format)
deparseJsonFormat(str, json_table_column->format);
if (json_table_column->pathspec)
{
appendStringInfoString(str, "PATH ");
deparseJsonTablePathSpec(str, json_table_column->pathspec);
}
break;
case JTC_NESTED:
Assert(false);
}
switch (json_table_column->wrapper)
{
case JSW_UNSPEC:
break;
case JSW_NONE:
if (json_table_column->coltype == JTC_REGULAR || json_table_column->coltype == JTC_FORMATTED)
appendStringInfoString(str, " WITHOUT WRAPPER");
break;
case JSW_CONDITIONAL:
appendStringInfoString(str, " WITH CONDITIONAL WRAPPER");
break;
case JSW_UNCONDITIONAL:
appendStringInfoString(str, " WITH UNCONDITIONAL WRAPPER");
break;
}
deparseJsonQuotesClauseOpt(str, json_table_column->quotes);
deparseJsonOnEmptyClauseOpt(str, json_table_column->on_empty);
deparseJsonOnErrorClauseOpt(str, json_table_column->on_error);
}
static void deparseJsonTableColumns(StringInfo str, List *json_table_columns)
{
appendStringInfoString(str, " COLUMNS (");
ListCell *lc = NULL;
foreach(lc, json_table_columns)
{
deparseJsonTableColumn(str, castNode(JsonTableColumn, lfirst(lc)));
if (lnext(json_table_columns, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
static void deparseJsonTable(StringInfo str, JsonTable *json_table)
{
appendStringInfoString(str, "JSON_TABLE(");
deparseJsonValueExpr(str, json_table->context_item);
appendStringInfoString(str, ", ");
deparseJsonTablePathSpec(str, json_table->pathspec);
if (json_table->passing)
appendStringInfoString(str, " PASSING ");
ListCell *lc = NULL;
foreach (lc, json_table->passing)
{
JsonArgument *json_argument = castNode(JsonArgument, lfirst(lc));
deparseJsonValueExpr(str, json_argument->val);
appendStringInfoString(str, " AS ");
deparseColLabel(str, json_argument->name);
if (lnext(json_table->passing, lc))
appendStringInfoString(str, ", ");
}
deparseJsonTableColumns(str, json_table->columns);
if (json_table->on_error)
{
deparseJsonBehavior(str, json_table->on_error);
appendStringInfoString(str, " ON ERROR");
}
appendStringInfoChar(str, ')');
if (json_table->alias)
{
appendStringInfoChar(str, ' ');
deparseAlias(str, json_table->alias);
}
}
static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
{
appendStringInfoString(str, "GROUPING(");
deparseExprList(str, grouping_func->args);
appendStringInfoChar(str, ')');
}
static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
{
appendStringInfoString(str, "CLUSTER ");
deparseUtilityOptionList(str, cluster_stmt->params);
if (cluster_stmt->relation != NULL)
{
deparseRangeVar(str, cluster_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ' ');
}
if (cluster_stmt->indexname != NULL)
{
appendStringInfoString(str, "USING ");
appendStringInfoString(str, quote_identifier(cluster_stmt->indexname));
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}
static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context)
{
if (!value) {
appendStringInfoString(str, "NULL");
return;
}
switch (nodeTag(value))
{
case T_Integer:
case T_Float:
deparseNumericOnly(str, value);
break;
case T_Boolean:
appendStringInfoString(str, value->boolval.boolval ? "true" : "false");
break;
case T_String:
if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
appendStringInfoString(str, quote_identifier(value->sval.sval));
} else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
deparseStringLiteral(str, value->sval.sval);
} else {
appendStringInfoString(str, value->sval.sval);
}
break;
case T_BitString:
if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
{
appendStringInfoChar(str, 'x');
deparseStringLiteral(str, value->sval.sval + 1);
}
else if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'b')
{
appendStringInfoChar(str, 'b');
deparseStringLiteral(str, value->sval.sval + 1);
}
else
{
Assert(false);
}
break;
default:
elog(ERROR, "deparse: unrecognized value node type: %d",
(int) nodeTag(value));
break;
}
}
static void deparsePreparableStmt(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_SelectStmt:
deparseSelectStmt(str, castNode(SelectStmt, node));
break;
case T_InsertStmt:
deparseInsertStmt(str, castNode(InsertStmt, node));
break;
case T_UpdateStmt:
deparseUpdateStmt(str, castNode(UpdateStmt, node));
break;
case T_DeleteStmt:
deparseDeleteStmt(str, castNode(DeleteStmt, node));
break;
case T_MergeStmt:
deparseMergeStmt(str, castNode(MergeStmt, node));
break;
default:
Assert(false);
}
}
static void deparseRuleActionStmt(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_SelectStmt:
deparseSelectStmt(str, castNode(SelectStmt, node));
break;
case T_InsertStmt:
deparseInsertStmt(str, castNode(InsertStmt, node));
break;
case T_UpdateStmt:
deparseUpdateStmt(str, castNode(UpdateStmt, node));
break;
case T_DeleteStmt:
deparseDeleteStmt(str, castNode(DeleteStmt, node));
break;
case T_NotifyStmt:
deparseNotifyStmt(str, castNode(NotifyStmt, node));
break;
default:
Assert(false);
}
}
static void deparseExplainableStmt(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_SelectStmt:
deparseSelectStmt(str, castNode(SelectStmt, node));
break;
case T_InsertStmt:
deparseInsertStmt(str, castNode(InsertStmt, node));
break;
case T_UpdateStmt:
deparseUpdateStmt(str, castNode(UpdateStmt, node));
break;
case T_DeleteStmt:
deparseDeleteStmt(str, castNode(DeleteStmt, node));
break;
case T_DeclareCursorStmt:
deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
break;
case T_CreateTableAsStmt:
deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
break;
case T_RefreshMatViewStmt:
deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
break;
case T_ExecuteStmt:
deparseExecuteStmt(str, castNode(ExecuteStmt, node));
break;
case T_MergeStmt:
deparseMergeStmt(str, castNode(MergeStmt, node));
break;
default:
Assert(false);
}
}
static void deparseSchemaStmt(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_CreateStmt:
deparseCreateStmt(str, castNode(CreateStmt, node), false);
break;
case T_IndexStmt:
deparseIndexStmt(str, castNode(IndexStmt, node));
break;
case T_CreateSeqStmt:
deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
break;
case T_CreateTrigStmt:
deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
break;
case T_GrantStmt:
deparseGrantStmt(str, castNode(GrantStmt, node));
break;
case T_ViewStmt:
deparseViewStmt(str, castNode(ViewStmt, node));
break;
default:
Assert(false);
}
}
static void deparseStmt(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_AlterEventTrigStmt:
deparseAlterEventTrigStmt(str, castNode(AlterEventTrigStmt, node));
break;
case T_AlterCollationStmt:
deparseAlterCollationStmt(str, castNode(AlterCollationStmt, node));
break;
case T_AlterDatabaseStmt:
deparseAlterDatabaseStmt(str, castNode(AlterDatabaseStmt, node));
break;
case T_AlterDatabaseSetStmt:
deparseAlterDatabaseSetStmt(str, castNode(AlterDatabaseSetStmt, node));
break;
case T_AlterDefaultPrivilegesStmt:
deparseAlterDefaultPrivilegesStmt(str, castNode(AlterDefaultPrivilegesStmt, node));
break;
case T_AlterDomainStmt:
deparseAlterDomainStmt(str, castNode(AlterDomainStmt, node));
break;
case T_AlterEnumStmt:
deparseAlterEnumStmt(str, castNode(AlterEnumStmt, node));
break;
case T_AlterExtensionStmt:
deparseAlterExtensionStmt(str, castNode(AlterExtensionStmt, node));
break;
case T_AlterExtensionContentsStmt:
deparseAlterExtensionContentsStmt(str, castNode(AlterExtensionContentsStmt, node));
break;
case T_AlterFdwStmt:
deparseAlterFdwStmt(str, castNode(AlterFdwStmt, node));
break;
case T_AlterForeignServerStmt:
deparseAlterForeignServerStmt(str, castNode(AlterForeignServerStmt, node));
break;
case T_AlterFunctionStmt:
deparseAlterFunctionStmt(str, castNode(AlterFunctionStmt, node));
break;
case T_AlterObjectDependsStmt:
deparseAlterObjectDependsStmt(str, castNode(AlterObjectDependsStmt, node));
break;
case T_AlterObjectSchemaStmt:
deparseAlterObjectSchemaStmt(str, castNode(AlterObjectSchemaStmt, node));
break;
case T_AlterOwnerStmt:
deparseAlterOwnerStmt(str, castNode(AlterOwnerStmt, node));
break;
case T_AlterOperatorStmt:
deparseAlterOperatorStmt(str, castNode(AlterOperatorStmt, node));
break;
case T_AlterTypeStmt:
deparseAlterTypeStmt(str, castNode(AlterTypeStmt, node));
break;
case T_AlterPolicyStmt:
deparseAlterPolicyStmt(str, castNode(AlterPolicyStmt, node));
break;
case T_AlterSeqStmt:
deparseAlterSeqStmt(str, castNode(AlterSeqStmt, node));
break;
case T_AlterSystemStmt:
deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
break;
case T_AlterTableMoveAllStmt:
deparseAlterTableMoveAllStmt(str, castNode(AlterTableMoveAllStmt, node));
break;
case T_AlterTableStmt:
deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
break;
case T_AlterTableSpaceOptionsStmt: deparseAlterTableSpaceOptionsStmt(str, castNode(AlterTableSpaceOptionsStmt, node));
break;
case T_AlterPublicationStmt:
deparseAlterPublicationStmt(str, castNode(AlterPublicationStmt, node));
break;
case T_AlterRoleSetStmt:
deparseAlterRoleSetStmt(str, castNode(AlterRoleSetStmt, node));
break;
case T_AlterRoleStmt:
deparseAlterRoleStmt(str, castNode(AlterRoleStmt, node));
break;
case T_AlterSubscriptionStmt:
deparseAlterSubscriptionStmt(str, castNode(AlterSubscriptionStmt, node));
break;
case T_AlterStatsStmt:
deparseAlterStatsStmt(str, castNode(AlterStatsStmt, node));
break;
case T_AlterTSConfigurationStmt:
deparseAlterTSConfigurationStmt(str, castNode(AlterTSConfigurationStmt, node));
break;
case T_AlterTSDictionaryStmt:
deparseAlterTSDictionaryStmt(str, castNode(AlterTSDictionaryStmt, node));
break;
case T_AlterUserMappingStmt:
deparseAlterUserMappingStmt(str, castNode(AlterUserMappingStmt, node));
break;
case T_CallStmt:
deparseCallStmt(str, castNode(CallStmt, node));
break;
case T_CheckPointStmt:
deparseCheckPointStmt(str, castNode(CheckPointStmt, node));
break;
case T_ClosePortalStmt:
deparseClosePortalStmt(str, castNode(ClosePortalStmt, node));
break;
case T_ClusterStmt:
deparseClusterStmt(str, castNode(ClusterStmt, node));
break;
case T_CommentStmt:
deparseCommentStmt(str, castNode(CommentStmt, node));
break;
case T_ConstraintsSetStmt:
deparseConstraintsSetStmt(str, castNode(ConstraintsSetStmt, node));
break;
case T_CopyStmt:
deparseCopyStmt(str, castNode(CopyStmt, node));
break;
case T_CreateAmStmt:
deparseCreateAmStmt(str, castNode(CreateAmStmt, node));
break;
case T_CreateTableAsStmt: deparseCreateTableAsStmt(str, castNode(CreateTableAsStmt, node));
break;
case T_CreateCastStmt:
deparseCreateCastStmt(str, castNode(CreateCastStmt, node));
break;
case T_CreateConversionStmt:
deparseCreateConversionStmt(str, castNode(CreateConversionStmt, node));
break;
case T_CreateDomainStmt:
deparseCreateDomainStmt(str, castNode(CreateDomainStmt, node));
break;
case T_CreateExtensionStmt:
deparseCreateExtensionStmt(str, castNode(CreateExtensionStmt, node));
break;
case T_CreateFdwStmt:
deparseCreateFdwStmt(str, castNode(CreateFdwStmt, node));
break;
case T_CreateForeignServerStmt:
deparseCreateForeignServerStmt(str, castNode(CreateForeignServerStmt, node));
break;
case T_CreateForeignTableStmt:
deparseCreateForeignTableStmt(str, castNode(CreateForeignTableStmt, node));
break;
case T_CreateFunctionStmt:
deparseCreateFunctionStmt(str, castNode(CreateFunctionStmt, node));
break;
case T_CreateOpClassStmt:
deparseCreateOpClassStmt(str, castNode(CreateOpClassStmt, node));
break;
case T_CreateOpFamilyStmt:
deparseCreateOpFamilyStmt(str, castNode(CreateOpFamilyStmt, node));
break;
case T_CreatePublicationStmt:
deparseCreatePublicationStmt(str, castNode(CreatePublicationStmt, node));
break;
case T_AlterOpFamilyStmt:
deparseAlterOpFamilyStmt(str, castNode(AlterOpFamilyStmt, node));
break;
case T_CreatePolicyStmt:
deparseCreatePolicyStmt(str, castNode(CreatePolicyStmt, node));
break;
case T_CreatePLangStmt:
deparseCreatePLangStmt(str, castNode(CreatePLangStmt, node));
break;
case T_CreateSchemaStmt:
deparseCreateSchemaStmt(str, castNode(CreateSchemaStmt, node));
break;
case T_CreateSeqStmt:
deparseCreateSeqStmt(str, castNode(CreateSeqStmt, node));
break;
case T_CreateStmt:
deparseCreateStmt(str, castNode(CreateStmt, node), false);
break;
case T_CreateSubscriptionStmt:
deparseCreateSubscriptionStmt(str, castNode(CreateSubscriptionStmt, node));
break;
case T_CreateStatsStmt:
deparseCreateStatsStmt(str, castNode(CreateStatsStmt, node));
break;
case T_CreateTableSpaceStmt:
deparseCreateTableSpaceStmt(str, castNode(CreateTableSpaceStmt, node));
break;
case T_CreateTransformStmt:
deparseCreateTransformStmt(str, castNode(CreateTransformStmt, node));
break;
case T_CreateTrigStmt:
deparseCreateTrigStmt(str, castNode(CreateTrigStmt, node));
break;
case T_CreateEventTrigStmt:
deparseCreateEventTrigStmt(str, castNode(CreateEventTrigStmt, node));
break;
case T_CreateRoleStmt:
deparseCreateRoleStmt(str, castNode(CreateRoleStmt, node));
break;
case T_CreateUserMappingStmt:
deparseCreateUserMappingStmt(str, castNode(CreateUserMappingStmt, node));
break;
case T_CreatedbStmt:
deparseCreatedbStmt(str, castNode(CreatedbStmt, node));
break;
case T_DeallocateStmt:
deparseDeallocateStmt(str, castNode(DeallocateStmt, node));
break;
case T_DeclareCursorStmt:
deparseDeclareCursorStmt(str, castNode(DeclareCursorStmt, node));
break;
case T_DefineStmt:
deparseDefineStmt(str, castNode(DefineStmt, node));
break;
case T_DeleteStmt:
deparseDeleteStmt(str, castNode(DeleteStmt, node));
break;
case T_DiscardStmt:
deparseDiscardStmt(str, castNode(DiscardStmt, node));
break;
case T_DoStmt:
deparseDoStmt(str, castNode(DoStmt, node));
break;
case T_DropOwnedStmt:
deparseDropOwnedStmt(str, castNode(DropOwnedStmt, node));
break;
case T_DropStmt:
deparseDropStmt(str, castNode(DropStmt, node));
break;
case T_DropSubscriptionStmt:
deparseDropSubscriptionStmt(str, castNode(DropSubscriptionStmt, node));
break;
case T_DropTableSpaceStmt:
deparseDropTableSpaceStmt(str, castNode(DropTableSpaceStmt, node));
break;
case T_DropRoleStmt:
deparseDropRoleStmt(str, castNode(DropRoleStmt, node));
break;
case T_DropUserMappingStmt:
deparseDropUserMappingStmt(str, castNode(DropUserMappingStmt, node));
break;
case T_DropdbStmt:
deparseDropdbStmt(str, castNode(DropdbStmt, node));
break;
case T_ExecuteStmt:
deparseExecuteStmt(str, castNode(ExecuteStmt, node));
break;
case T_ExplainStmt:
deparseExplainStmt(str, castNode(ExplainStmt, node));
break;
case T_FetchStmt:
deparseFetchStmt(str, castNode(FetchStmt, node));
break;
case T_GrantStmt:
deparseGrantStmt(str, castNode(GrantStmt, node));
break;
case T_GrantRoleStmt:
deparseGrantRoleStmt(str, castNode(GrantRoleStmt, node));
break;
case T_ImportForeignSchemaStmt:
deparseImportForeignSchemaStmt(str, castNode(ImportForeignSchemaStmt, node));
break;
case T_IndexStmt:
deparseIndexStmt(str, castNode(IndexStmt, node));
break;
case T_InsertStmt:
deparseInsertStmt(str, castNode(InsertStmt, node));
break;
case T_ListenStmt:
deparseListenStmt(str, castNode(ListenStmt, node));
break;
case T_RefreshMatViewStmt:
deparseRefreshMatViewStmt(str, castNode(RefreshMatViewStmt, node));
break;
case T_LoadStmt:
deparseLoadStmt(str, castNode(LoadStmt, node));
break;
case T_LockStmt:
deparseLockStmt(str, castNode(LockStmt, node));
break;
case T_MergeStmt:
deparseMergeStmt(str, castNode(MergeStmt, node));
break;
case T_NotifyStmt:
deparseNotifyStmt(str, castNode(NotifyStmt, node));
break;
case T_PrepareStmt:
deparsePrepareStmt(str, castNode(PrepareStmt, node));
break;
case T_ReassignOwnedStmt:
deparseReassignOwnedStmt(str, castNode(ReassignOwnedStmt, node));
break;
case T_ReindexStmt:
deparseReindexStmt(str, castNode(ReindexStmt, node));
break;
case T_RenameStmt:
deparseRenameStmt(str, castNode(RenameStmt, node));
break;
case T_RuleStmt:
deparseRuleStmt(str, castNode(RuleStmt, node));
break;
case T_SecLabelStmt:
deparseSecLabelStmt(str, castNode(SecLabelStmt, node));
break;
case T_SelectStmt:
deparseSelectStmt(str, castNode(SelectStmt, node));
break;
case T_TransactionStmt:
deparseTransactionStmt(str, castNode(TransactionStmt, node));
break;
case T_TruncateStmt:
deparseTruncateStmt(str, castNode(TruncateStmt, node));
break;
case T_UnlistenStmt:
deparseUnlistenStmt(str, castNode(UnlistenStmt, node));
break;
case T_UpdateStmt:
deparseUpdateStmt(str, castNode(UpdateStmt, node));
break;
case T_VacuumStmt:
deparseVacuumStmt(str, castNode(VacuumStmt, node));
break;
case T_VariableSetStmt:
deparseVariableSetStmt(str, castNode(VariableSetStmt, node));
break;
case T_VariableShowStmt:
deparseVariableShowStmt(str, castNode(VariableShowStmt, node));
break;
case T_ViewStmt:
deparseViewStmt(str, castNode(ViewStmt, node));
break;
case T_CompositeTypeStmt:
deparseCompositeTypeStmt(str, castNode(CompositeTypeStmt, node));
break;
case T_CreateEnumStmt:
deparseCreateEnumStmt(str, castNode(CreateEnumStmt, node));
break;
case T_CreateRangeStmt:
deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
break;
default:
elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
}
}