ext/pg_query/pg_query_deparse.c (8,710 lines of code) (raw):
#include "pg_query.h"
#include "pg_query_internal.h"
#include "pg_query_readfuncs.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 "limits.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,
// Parent node type (and sometimes field)
DEPARSE_NODE_CONTEXT_INSERT_RELATION,
DEPARSE_NODE_CONTEXT_INSERT_ON_CONFLICT,
DEPARSE_NODE_CONTEXT_UPDATE,
DEPARSE_NODE_CONTEXT_RETURNING,
DEPARSE_NODE_CONTEXT_A_EXPR,
DEPARSE_NODE_CONTEXT_XMLATTRIBUTES,
DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
DEPARSE_NODE_CONTEXT_CREATE_TYPE,
DEPARSE_NODE_CONTEXT_ALTER_TYPE,
// Identifier vs constant context
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';
}
}
/*
* Append a SQL string literal representing "val" to buf.
*
* Copied here from postgres_fdw/deparse.c to avoid adding
* many additional dependencies.
*/
static void
deparseStringLiteral(StringInfo buf, const char *val)
{
const char *valptr;
/*
* Rather than making assumptions about the remote server's value of
* standard_conforming_strings, always use E'foo' syntax if there are any
* backslashes. This will fail on remote servers before 8.1, but those
* are long out of support.
*/
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, '\'');
}
// Check whether the value is a reserved keyword, to determine escaping for output
//
// Note that since the parser lowercases all keywords, this does *not* match when the
// value is not all-lowercase and a reserved keyword.
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;
}
// Returns whether the given value consists only of operator characters
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);
static 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);
static void deparseTypeName(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);
static void deparseMinMaxExpr(StringInfo str, MinMaxExpr *min_max_expr);
static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr);
static void deparseXmlSerialize(StringInfo str, XmlSerialize *xml_serialize);
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 deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr);
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, Value *value, DeparseNodeContext context);
// "any_name" in gram.y
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, '.');
}
}
}
// "a_expr" / "b_expr" in gram.y
static void deparseExpr(StringInfo str, Node *node)
{
switch (nodeTag(node))
{
case T_FuncCall:
deparseFuncCall(str, castNode(FuncCall, node));
break;
case T_XmlExpr:
deparseXmlExpr(str, castNode(XmlExpr, node));
break;
case T_TypeCast:
deparseTypeCast(str, castNode(TypeCast, node));
break;
case T_A_Const:
deparseAConst(str, castNode(A_Const, node));
break;
case T_ColumnRef:
deparseColumnRef(str, castNode(ColumnRef, node));
break;
case T_A_Expr:
deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
break;
case T_CaseExpr:
deparseCaseExpr(str, castNode(CaseExpr, node));
break;
case T_A_ArrayExpr:
deparseAArrayExpr(str, castNode(A_ArrayExpr, node));
break;
case T_NullTest:
deparseNullTest(str, castNode(NullTest, node));
break;
case T_XmlSerialize:
deparseXmlSerialize(str, castNode(XmlSerialize, node));
break;
case T_ParamRef:
deparseParamRef(str, castNode(ParamRef, node));
break;
case T_BoolExpr:
deparseBoolExpr(str, castNode(BoolExpr, node));
break;
case T_SubLink:
deparseSubLink(str, castNode(SubLink, node));
break;
case T_RowExpr:
deparseRowExpr(str, castNode(RowExpr, node));
break;
case T_CoalesceExpr:
deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
break;
case T_SetToDefault:
deparseSetToDefault(str, castNode(SetToDefault, node));
break;
case T_A_Indirection:
deparseAIndirection(str, castNode(A_Indirection, node));
break;
case T_CollateClause:
deparseCollateClause(str, castNode(CollateClause, node));
break;
case T_CurrentOfExpr:
deparseCurrentOfExpr(str, castNode(CurrentOfExpr, node));
break;
case T_SQLValueFunction:
deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
break;
case T_MinMaxExpr:
deparseMinMaxExpr(str, castNode(MinMaxExpr, node));
break;
case T_BooleanTest:
deparseBooleanTest(str, castNode(BooleanTest, node));
break;
case T_GroupingFunc:
deparseGroupingFunc(str, castNode(GroupingFunc, node));
break;
default:
Assert(false);
elog(ERROR, "unpermitted node type in a_expr/b_expr: %d",
(int) nodeTag(node));
break;
}
}
// "c_expr" in gram.y
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_TypeCast:
deparseTypeCast(str, castNode(TypeCast, node));
break;
case T_A_Expr:
appendStringInfoChar(str, '(');
deparseAExpr(str, castNode(A_Expr, node), DEPARSE_NODE_CONTEXT_NONE);
appendStringInfoChar(str, ')');
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_FuncCall:
deparseFuncCall(str, castNode(FuncCall, 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;
default:
Assert(false);
elog(ERROR, "unpermitted node type in c_expr: %d",
(int) nodeTag(node));
break;
}
}
// "expr_list" in gram.y
static void deparseExprList(StringInfo str, List *exprs)
{
ListCell *lc;
foreach(lc, exprs)
{
deparseExpr(str, lfirst(lc));
if (lnext(exprs, lc))
appendStringInfoString(str, ", ");
}
}
// "ColId", "name", "database_name", "access_method" and "index_name" in gram.y
static void deparseColId(StringInfo str, char *s)
{
appendStringInfoString(str, quote_identifier(s));
}
// "ColLabel", "attr_name"
//
// Note this is kept separate from ColId in case we ever want to be more
// specific on how to handle keywords here
static void deparseColLabel(StringInfo str, char *s)
{
appendStringInfoString(str, quote_identifier(s));
}
// "SignedIconst" and "Iconst" in gram.y
static void deparseSignedIconst(StringInfo str, Node *node)
{
appendStringInfo(str, "%d", intVal(node));
}
// "indirection" and "opt_indirection" in gram.y
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
{
// No other nodes should appear here
Assert(false);
}
}
}
// "role_list" in gram.y
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, ", ");
}
}
// "SimpleTypename" in gram.y
static void deparseSimpleTypename(StringInfo str, Node *node)
{
deparseTypeName(str, castNode(TypeName, node));
}
// "NumericOnly" in gram.y
static void deparseNumericOnly(StringInfo str, Value *value)
{
switch (nodeTag(value))
{
case T_Integer:
appendStringInfo(str, "%d", value->val.ival);
break;
case T_Float:
appendStringInfoString(str, value->val.str);
break;
default:
Assert(false);
}
}
// "NumericOnly_list" in gram.y
static void deparseNumericOnlyList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseNumericOnly(str, (Value *) lfirst(lc));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "SeqOptElem" in gram.y
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, (Value *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "CYCLE");
}
else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NO CYCLE");
}
else if (strcmp(def_elem->defname, "increment") == 0)
{
appendStringInfoString(str, "INCREMENT ");
deparseNumericOnly(str, (Value *) def_elem->arg);
}
else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
{
appendStringInfoString(str, "MAXVALUE ");
deparseNumericOnly(str, (Value *) 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, (Value *) 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, (Value *) 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, (Value *) def_elem->arg);
}
else
{
Assert(false);
}
}
// "SeqOptList" in gram.y
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, ' ');
}
}
// "OptSeqOptList" in gram.y
static void deparseOptSeqOptList(StringInfo str, List *options)
{
if (list_length(options) > 0)
deparseSeqOptList(str, options);
}
// "OptParenthesizedSeqOptList" in gram.y
static void deparseOptParenthesizedSeqOptList(StringInfo str, List *options)
{
if (list_length(options) > 0)
{
appendStringInfoChar(str, '(');
deparseSeqOptList(str, options);
appendStringInfoChar(str, ')');
}
}
// "opt_drop_behavior" in gram.y
static void deparseOptDropBehavior(StringInfo str, DropBehavior behavior)
{
switch (behavior)
{
case DROP_RESTRICT:
// Default
break;
case DROP_CASCADE:
appendStringInfoString(str, "CASCADE ");
break;
}
}
// "any_operator" in gram.y
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);
}
}
// "qual_Op" and "qual_all_Op" in gram.y
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, ")");
}
}
// "subquery_Op" in gram.y
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, ")");
}
}
// Not present directly in gram.y (usually matched by ColLabel)
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);
}
// "def_arg" and "operator_def_arg" in gram.y
static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
{
if (IsA(arg, TypeName)) // func_type
{
deparseTypeName(str, castNode(TypeName, arg));
}
else if (IsA(arg, List)) // qual_all_Op
{
List *l = castNode(List, arg);
Assert(list_length(l) == 1 || list_length(l) == 2);
// Schema qualified operator
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)) // NumericOnly
{
deparseValue(str, (Value *) 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) // NONE
{
appendStringInfoString(str, "NONE");
}
else if (isReservedKeyword(s)) // reserved_keyword
{
appendStringInfoString(str, s);
}
else // Sconst
{
deparseStringLiteral(str, s);
}
}
else
{
Assert(false);
}
}
// "definition" in gram.y
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, ')');
}
// "opt_definition" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseOptDefinition(StringInfo str, List *options)
{
if (list_length(options) > 0)
{
appendStringInfoString(str, "WITH ");
deparseDefinition(str, options);
}
}
// "create_generic_options" in gram.y
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, ") ");
}
// "common_func_opt_item" in gram.y
static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
{
if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
}
else if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 0)
{
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 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "SECURITY DEFINER");
}
else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "SECURITY INVOKER");
}
else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "LEAKPROOF");
}
else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOT LEAKPROOF");
}
else if (strcmp(def_elem->defname, "cost") == 0)
{
appendStringInfoString(str, "COST ");
deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
}
else if (strcmp(def_elem->defname, "rows") == 0)
{
appendStringInfoString(str, "ROWS ");
deparseValue(str, (Value *) 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)) // FunctionSetResetClause
{
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);
}
}
// "NonReservedWord_or_Sconst" in gram.y
//
// Note since both identifiers and string constants are allowed here, we
// currently always return an identifier, except:
//
// 1) when the string is empty (since an empty identifier can't be scanned)
// 2) when the value is equal or larger than NAMEDATALEN (64+ characters)
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));
}
// "func_as" in gram.y
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, ", ");
}
}
// "createfunc_opt_item" in gram.y
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);
}
}
// "alter_generic_options" in gram.y
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, ") ");
}
// "func_name" in gram.y
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, '.');
}
}
// "function_with_argtypes" in gram.y
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, '(');
foreach(lc, object_with_args->objargs)
{
if (IsA(lfirst(lc), TypeName))
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
else
deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
if (lnext(object_with_args->objargs, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ')');
}
}
// "function_with_argtypes_list" in gram.y
static void deparseFunctionWithArgtypesList(StringInfo str, List *l)
{
ListCell *lc;
foreach(lc, l)
{
deparseFunctionWithArgtypes(str, castNode(ObjectWithArgs, lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "operator_with_argtypes" in gram.y
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, ')');
}
// "aggr_args" in gram.y
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)));
}
// Repeat the last direct arg as a ordered arg to handle the
// simplification done by makeOrderedSetArgs in gram.y
if (order_by_pos == list_length(args))
{
appendStringInfoString(str, " ORDER BY ");
deparseFunctionParameter(str, castNode(FunctionParameter, llast(args)));
}
}
appendStringInfoChar(str, ')');
}
// "aggregate_with_argtypes" in gram.y
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)
{
appendStringInfoChar(str, '*');
}
else
{
foreach(lc, object_with_args->objargs)
{
deparseTypeName(str, castNode(TypeName, lfirst(lc)));
if (lnext(object_with_args->objargs, lc))
appendStringInfoString(str, ", ");
}
}
appendStringInfoChar(str, ')');
}
// "columnList" in gram.y
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, ", ");
}
}
// "OptTemp" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseOptTemp(StringInfo str, char relpersistence)
{
switch (relpersistence)
{
case RELPERSISTENCE_PERMANENT:
// Default
break;
case RELPERSISTENCE_UNLOGGED:
appendStringInfoString(str, "UNLOGGED ");
break;
case RELPERSISTENCE_TEMP:
appendStringInfoString(str, "TEMPORARY ");
break;
default:
Assert(false);
break;
}
}
// "relation_expr_list" in gram.y
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, ", ");
}
}
// "handler_name" in gram.y
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, '.');
}
}
// "fdw_options" in gram.y
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, ' ');
}
}
// "type_list" in gram.y
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, ", ");
}
}
// "opt_boolean_or_string" in gram.y
static void deparseOptBooleanOrString(StringInfo str, char *s)
{
if (s == NULL)
return; // No value set
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);
}
// "var_name"
//
// Note this is kept separate from ColId in case we want to improve the
// output of namespaced variable names
static void deparseVarName(StringInfo str, char *s)
{
deparseColId(str, s);
}
// "var_list"
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, (Value *) &a_const->val);
else if (IsA(&a_const->val, String))
deparseOptBooleanOrString(str, strVal(&a_const->val));
else
Assert(false);
}
else
{
Assert(false);
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "transaction_mode_list" in gram.y
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, ", ");
}
}
// "alter_identity_column_option_list" in gram.y
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, (Value *) 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, ' ');
}
}
// "reloptions" in gram.y
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, ')');
}
// "OptWith" and "opt_reloptions" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseOptWith(StringInfo str, List *l)
{
ListCell *lc = NULL;
if (list_length(l) > 0)
{
appendStringInfoString(str, "WITH ");
deparseRelOptions(str, l);
appendStringInfoChar(str, ' ');
}
}
// "target_list" and "opt_target_list" in gram.y
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);
if (res_target->name != NULL) {
appendStringInfoString(str, " AS ");
appendStringInfoString(str, quote_identifier(res_target->name));
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "insert_column_list" in gram.y
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, ", ");
}
}
// "xml_attribute_list" in gram.y
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);
if (res_target->name != NULL)
{
appendStringInfoString(str, " AS ");
appendStringInfoString(str, quote_identifier(res_target->name));
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "xml_namespace_list" in gram.y
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);
if (res_target->name != NULL)
{
appendStringInfoString(str, " AS ");
appendStringInfoString(str, quote_identifier(res_target->name));
}
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "table_ref" in gram.y
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;
default:
Assert(false);
}
}
// "from_list" in gram.y
static void deparseFromList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseTableRef(str, lfirst(lc));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "from_clause" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseFromClause(StringInfo str, List *l)
{
if (list_length(l) > 0)
{
appendStringInfoString(str, "FROM ");
deparseFromList(str, l);
appendStringInfoChar(str, ' ');
}
}
// "where_clause" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseWhereClause(StringInfo str, Node *node)
{
if (node != NULL)
{
appendStringInfoString(str, "WHERE ");
deparseExpr(str, node);
appendStringInfoChar(str, ' ');
}
}
// "group_by_list" in gram.y
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));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "set_target" in gram.y
static void deparseSetTarget(StringInfo str, ResTarget *res_target)
{
Assert(res_target->name != NULL);
deparseColId(str, res_target->name);
deparseOptIndirection(str, res_target->indirection, 0);
}
// "any_name_list" in gram.y
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, ", ");
}
}
// "name_list" in gram.y
static void deparseNameList(StringInfo str, List *l)
{
ListCell *lc = NULL;
foreach(lc, l)
{
deparseColId(str, strVal(lfirst(lc)));
if (lnext(l, lc))
appendStringInfoString(str, ", ");
}
}
// "opt_sort_clause" in gram.y
//
// Note this method adds a trailing space if a value is output
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, ' ');
}
}
// "func_arg_expr" in gram.y
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);
}
else
{
deparseExpr(str, node);
}
}
// "set_clause_list" in gram.y
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) // Last element in this multi-assign
break;
else if (lnext(target_list, lc2))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") = ");
deparseExpr(str, r->source);
skip_next_n_elems = r->ncolumns - 1;
}
else
{
deparseSetTarget(str, res_target);
appendStringInfoString(str, " = ");
deparseExpr(str, res_target->val);
}
}
}
// "func_expr_windowless" in gram.y
static void deparseFuncExprWindowless(StringInfo str, Node* node)
{
switch (nodeTag(node))
{
case T_FuncCall:
deparseFuncCall(str, castNode(FuncCall, node));
break;
case T_SQLValueFunction:
deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
break;
case T_TypeCast:
deparseTypeCast(str, castNode(TypeCast, node));
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));
break;
case T_XmlSerialize:
deparseXmlSerialize(str, castNode(XmlSerialize, node));
break;
default:
Assert(false);
}
}
// "opt_collate" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseOptCollate(StringInfo str, List *l)
{
if (list_length(l) > 0)
{
appendStringInfoString(str, "COLLATE ");
deparseAnyName(str, l);
appendStringInfoChar(str, ' ');
}
}
// "index_elem" in gram.y
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_TypeCast:
case T_CoalesceExpr:
case T_MinMaxExpr:
case T_XmlExpr:
case T_XmlSerialize:
deparseFuncExprWindowless(str, index_elem->expr);
break;
default:
appendStringInfoChar(str, '(');
deparseExpr(str, index_elem->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:
// Default
break;
case SORTBY_ASC:
appendStringInfoString(str, "ASC ");
break;
case SORTBY_DESC:
appendStringInfoString(str, "DESC ");
break;
case SORTBY_USING:
// Not allowed in CREATE INDEX
Assert(false);
break;
}
switch (index_elem->nulls_ordering)
{
case SORTBY_NULLS_DEFAULT:
// Default
break;
case SORTBY_NULLS_FIRST:
appendStringInfoString(str, "NULLS FIRST ");
break;
case SORTBY_NULLS_LAST:
appendStringInfoString(str, "NULLS LAST ");
break;
}
removeTrailingSpace(str);
}
// "qualified_name_list" in gram.y
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, ", ");
}
}
// "OptInherit" in gram.y
//
// Note this method adds a trailing space if a value is output
static void deparseOptInherit(StringInfo str, List *l)
{
if (list_length(l) > 0)
{
appendStringInfoString(str, "INHERITS (");
deparseQualifiedNameList(str, l);
appendStringInfoString(str, ") ");
}
}
// "privilege_target" in gram.y
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:
// Other types are not supported here
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:
// Other types are not supported here
Assert(false);
break;
}
break;
case ACL_TARGET_DEFAULTS: // defacl_privilege_target
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:
// Other types are not supported here
Assert(false);
break;
}
break;
}
}
// "opclass_item_list" in gram.y
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, ", ");
}
}
// "createdb_opt_list" in gram.y
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 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 ");
deparseGroupByList(str, stmt->groupClause);
appendStringInfoChar(str, ' ');
}
if (stmt->havingClause != NULL)
{
appendStringInfoString(str, "HAVING ");
deparseExpr(str, stmt->havingClause);
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) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
appendStringInfoString(str, "ALL");
else
deparseCExpr(str, stmt->limitCount);
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);
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); /* target relation name */
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:
// No clause
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->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);
}
static void deparseRawStmt(StringInfo str, RawStmt *raw_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)
{
deparseValue(str, &a_const->val, DEPARSE_NODE_CONTEXT_CONSTANT);
}
static void deparseFuncCall(StringInfo str, FuncCall *func_call)
{
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)
{
/*
* Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
* keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
*/
appendStringInfoString(str, "OVERLAY(");
deparseExpr(str, linitial(func_call->args));
appendStringInfoString(str, " PLACING ");
deparseExpr(str, lsecond(func_call->args));
appendStringInfoString(str, " FROM ");
deparseExpr(str, lthird(func_call->args));
appendStringInfoString(str, " FOR ");
deparseExpr(str, lfourth(func_call->args));
appendStringInfoChar(str, ')');
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);
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;
// The parent node is responsible for outputting window_def->name
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 ");
// frame_start
if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
{
appendStringInfoString(str, "UNBOUNDED PRECEDING ");
}
else if (window_def->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
{
Assert(false); // disallowed
}
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);
appendStringInfoString(str, " PRECEDING ");
}
else if (window_def->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING)
{
Assert(window_def->startOffset != NULL);
deparseExpr(str, window_def->startOffset);
appendStringInfoString(str, " FOLLOWING ");
}
if (window_def->frameOptions & FRAMEOPTION_BETWEEN)
{
appendStringInfoString(str, "AND ");
// frame_end
if (window_def->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
{
Assert(false); // disallowed
}
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);
appendStringInfoString(str, " PRECEDING ");
}
else if (window_def->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING)
{
Assert(window_def->endOffset != NULL);
deparseExpr(str, window_def->endOffset);
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);
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);
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:
// Not present in raw parse trees
Assert(false);
return;
case EXPR_SUBLINK:
appendStringInfoString(str, "(");
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case MULTIEXPR_SUBLINK:
// Not present in raw parse trees
Assert(false);
return;
case ARRAY_SUBLINK:
appendStringInfoString(str, "ARRAY(");
deparseSelectStmt(str, castNode(SelectStmt, sub_link->subselect));
appendStringInfoChar(str, ')');
return;
case CTE_SUBLINK: /* for SubPlans only */
// Not present in raw parse trees
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, NullTest) || IsA(a_expr->lexpr, A_Expr));
bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
switch (a_expr->kind) {
case AEXPR_OP: /* normal operator */
{
bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
if (need_outer_parens)
appendStringInfoChar(str, '(');
if (a_expr->lexpr != NULL)
{
if (need_lexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->lexpr);
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);
if (need_rexpr_parens)
appendStringInfoChar(str, ')');
}
if (need_outer_parens)
appendStringInfoChar(str, ')');
}
return;
case AEXPR_OP_ANY: /* scalar op ANY (array) */
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, a_expr->name);
appendStringInfoString(str, " ANY(");
deparseExpr(str, a_expr->rexpr);
appendStringInfoChar(str, ')');
return;
case AEXPR_OP_ALL: /* scalar op ALL (array) */
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, a_expr->name);
appendStringInfoString(str, " ALL(");
deparseExpr(str, a_expr->rexpr);
appendStringInfoChar(str, ')');
return;
case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
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);
if (need_lexpr_parens)
appendStringInfoChar(str, ')');
appendStringInfoString(str, " IS DISTINCT FROM ");
if (need_rexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->rexpr);
if (need_rexpr_parens)
appendStringInfoChar(str, ')');
return;
case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
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);
appendStringInfoString(str, " IS NOT DISTINCT FROM ");
deparseExpr(str, a_expr->rexpr);
return;
case AEXPR_NULLIF: /* NULLIF - name must be "=" */
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);
appendStringInfoString(str, ", ");
deparseExpr(str, a_expr->rexpr);
appendStringInfoChar(str, ')');
return;
case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
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);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "=") == 0) {
appendStringInfoString(str, "IS OF ");
} else if (strcmp(name, "<>") == 0) {
appendStringInfoString(str, "IS NOT OF ");
} else {
Assert(false);
}
appendStringInfoChar(str, '(');
deparseTypeList(str, castNode(List, a_expr->rexpr));
appendStringInfoChar(str, ')');
return;
case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
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);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
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: /* [NOT] LIKE - name must be "~~" or "!~~" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "~~") == 0) {
appendStringInfoString(str, "LIKE ");
} else if (strcmp(name, "!~~") == 0) {
appendStringInfoString(str, "NOT LIKE ");
} else {
Assert(false);
}
deparseExpr(str, a_expr->rexpr);
return;
case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "~~*") == 0) {
appendStringInfoString(str, "ILIKE ");
} else if (strcmp(name, "!~~*") == 0) {
appendStringInfoString(str, "NOT ILIKE ");
} else {
Assert(false);
}
deparseExpr(str, a_expr->rexpr);
return;
case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
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));
if (list_length(n->args) == 2)
{
appendStringInfoString(str, " ESCAPE ");
deparseExpr(str, lsecond(n->args));
}
return;
case AEXPR_BETWEEN: /* name must be "BETWEEN" */
case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
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);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, strVal(linitial(a_expr->name)));
appendStringInfoChar(str, ' ');
foreach(lc, castNode(List, a_expr->rexpr)) {
deparseExpr(str, lfirst(lc));
if (lnext(castNode(List, a_expr->rexpr), lc))
appendStringInfoString(str, " AND ");
}
return;
case AEXPR_PAREN: /* nameless dummy node for parentheses */
// Not present in parse trees when operator_precedence_warning is turned off
Assert(false);
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)
{
// Put parantheses around AND + OR nodes that are inside
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));
if (need_parens)
appendStringInfoChar(str, ')');
if (lnext(bool_expr->args, lc))
appendStringInfoString(str, " AND ");
}
return;
case OR_EXPR:
foreach(lc, bool_expr->args)
{
// Put parantheses around AND + OR nodes that are inside
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));
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));
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);
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);
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"); // with precision
break;
case SVFOP_CURRENT_TIMESTAMP:
appendStringInfoString(str, "current_timestamp");
break;
case SVFOP_CURRENT_TIMESTAMP_N:
appendStringInfoString(str, "current_timestamp"); // with precision
break;
case SVFOP_LOCALTIME:
appendStringInfoString(str, "localtime");
break;
case SVFOP_LOCALTIME_N:
appendStringInfoString(str, "localtime"); // with precision
break;
case SVFOP_LOCALTIMESTAMP:
appendStringInfoString(str, "localtimestamp");
break;
case SVFOP_LOCALTIMESTAMP_N:
appendStringInfoString(str, "localtimestamp"); // with precision
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: /* matching tuple pairs only */
if (!join_expr->isNatural && join_expr->quals == NULL && list_length(join_expr->usingClause) == 0)
appendStringInfoString(str, "CROSS ");
break;
case JOIN_LEFT: /* pairs + unmatched LHS tuples */
appendStringInfoString(str, "LEFT ");
break;
case JOIN_FULL: /* pairs + unmatched LHS + unmatched RHS */
appendStringInfoString(str, "FULL ");
break;
case JOIN_RIGHT: /* pairs + unmatched RHS tuples */
appendStringInfoString(str, "RIGHT ");
break;
case JOIN_SEMI:
case JOIN_ANTI:
case JOIN_UNIQUE_OUTER:
case JOIN_UNIQUE_INNER:
// Only used by the planner/executor, not seen in parser output
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);
appendStringInfoChar(str, ' ');
}
if (list_length(join_expr->usingClause) > 0)
{
appendStringInfoString(str, "USING (");
deparseNameList(str, join_expr->usingClause);
appendStringInfoString(str, ") ");
}
if (need_alias_parens)
appendStringInfoString(str, ") ");
if (join_expr->alias != NULL)
deparseAlias(str, join_expr->alias);
removeTrailingSpace(str);
}
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: /* no option specified */
break;
case CTEMaterializeAlways:
appendStringInfoString(str, "MATERIALIZED ");
break;
case CTEMaterializeNever:
appendStringInfoString(str, "NOT MATERIALIZED ");
break;
}
appendStringInfoChar(str, '(');
deparsePreparableStmt(str, cte->ctequery);
appendStringInfoChar(str, ')');
}
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_EXPLICIT_CAST:
// Not present in raw parser output
Assert(false);
break;
case COERCE_IMPLICIT_CAST:
// No prefix
break;
}
appendStringInfoString(str, "(");
deparseExprList(str, row_expr->args);
appendStringInfoChar(str, ')');
}
static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
{
bool need_parens = false;
Assert(type_cast->typeName != NULL);
if (IsA(type_cast->arg, A_Expr))
{
appendStringInfoString(str, "CAST(");
deparseExpr(str, type_cast->arg);
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))
{
/*
* Handle "bool" or "false" in the statement, which is represented as a typecast
* (other boolean casts should be represented as a cast, i.e. don't need special handling)
*/
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;
}
}
}
// Ensure negative values have wrapping parentheses
if (IsA(&a_const->val, Float) || (IsA(&a_const->val, Integer) && intVal(&a_const->val) < 0))
{
need_parens = true;
}
}
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, type_cast->arg);
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)
{
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);
appendStringInfoString(str, "interval");
// This logic is based on intervaltypmodout in timestamp.c
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:
// Nothing
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);
}
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 deparseNullTest(StringInfo str, NullTest *null_test)
{
// argisrow is always false in raw parser output
Assert(null_test->argisrow == false);
deparseExpr(str, (Node *) null_test->arg);
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);
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);
appendStringInfoChar(str, ' ');
}
appendStringInfoString(str, "END");
}
static void deparseCaseWhen(StringInfo str, CaseWhen *case_when)
{
appendStringInfoString(str, "WHEN ");
deparseExpr(str, (Node *) case_when->expr);
appendStringInfoString(str, " THEN ");
deparseExpr(str, (Node *) case_when->result);
}
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));
if (need_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_indirection->arg);
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);
if (a_indices->is_slice)
appendStringInfoChar(str, ':');
if (a_indices->uidx != NULL)
deparseExpr(str, a_indices->uidx);
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)
{
deparseExpr(str, (Node *) boolean_test->arg);
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, column_def->colname);
appendStringInfoChar(str, ' ');
}
if (column_def->typeName != NULL)
{
deparseTypeName(str, column_def->typeName);
appendStringInfoChar(str, ' ');
}
if (column_def->raw_default != NULL)
{
appendStringInfoString(str, "USING ");
deparseExpr(str, column_def->raw_default);
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 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, ") ");
}
switch (insert_stmt->override)
{
case OVERRIDING_NOT_SET:
// Do nothing
break;
case OVERRIDING_USER_VALUE:
appendStringInfoString(str, "OVERRIDING USER VALUE ");
break;
case OVERRIDING_SYSTEM_VALUE:
appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
break;
}
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);
deparseWhereClause(str, update_stmt->whereClause);
if (list_length(update_stmt->returningList) > 0)
{
appendStringInfoString(str, "RETURNING ");
deparseTargetList(str, update_stmt->returningList);
}
removeTrailingSpace(str);
}
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, ' ');
}
deparseWhereClause(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:
/* no such clause - only used in PlanRowMark */
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:
// Default
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_EXPLICIT:
// Default
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_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, 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 ");
deparseExpr(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);
appendStringInfoString(str, ") STORED ");
break;
case CONSTR_CHECK:
appendStringInfoString(str, "CHECK (");
deparseExpr(str, constraint->raw_expr);
appendStringInfoString(str, ") ");
break;
case CONSTR_PRIMARY:
appendStringInfoString(str, "PRIMARY KEY ");
break;
case CONSTR_UNIQUE:
appendStringInfoString(str, "UNIQUE ");
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);
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)
{
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:
// Default
break;
case FKCONSTR_MATCH_FULL:
appendStringInfoString(str, "MATCH FULL ");
break;
case FKCONSTR_MATCH_PARTIAL:
// Not implemented in Postgres
Assert(false);
break;
default:
// Not specified
break;
}
switch (constraint->fk_upd_action)
{
case FKCONSTR_ACTION_NOACTION:
// Default
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:
// Not specified
break;
}
switch (constraint->fk_del_action)
{
case FKCONSTR_ACTION_NOACTION:
// Default
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:
appendStringInfoString(str, "ON DELETE SET NULL ");
break;
case FKCONSTR_ACTION_SETDEFAULT:
appendStringInfoString(str, "ON DELETE SET DEFAULT ");
break;
default:
// Not specified
break;
}
if (list_length(constraint->including) > 0)
{
appendStringInfoString(str, "INCLUDE (");
deparseColumnList(str, constraint->including);
appendStringInfoString(str, ") ");
}
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 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, ' ');
}
removeTrailingSpace(str);
}
static void deparseFunctionParameter(StringInfo str, FunctionParameter *function_parameter)
{
switch (function_parameter->mode)
{
case FUNC_PARAM_IN: /* input only */
// Default
break;
case FUNC_PARAM_OUT: /* output only */
appendStringInfoString(str, "OUT ");
break;
case FUNC_PARAM_INOUT: /* both */
appendStringInfoString(str, "INOUT ");
break;
case FUNC_PARAM_VARIADIC: /* variadic (always input) */
appendStringInfoString(str, "VARIADIC ");
break;
case FUNC_PARAM_TABLE: /* table function output column */
// No special annotation, the caller is expected to correctly put
// this into the RETURNS part of the CREATE FUNCTION statement
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);
}
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, ' ');
}
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_USER:
appendStringInfoString(str, "CURRENT_USER");
break;
case ROLESPEC_SESSION_USER:
appendStringInfoString(str, "SESSION_USER");
break;
case ROLESPEC_PUBLIC:
appendStringInfoString(str, "public");
break;
}
}
// "part_elem" in gram.y
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);
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 ");
appendStringInfoString(str, partition_spec->strategy);
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);
}
}
// "TableElement" in gram.y
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)
{
// In raw parse output tableElts contains both columns and constraints
// (and the constraints field is NIL)
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:
// No ON COMMIT clause
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, (Value *) 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:
// Not supported in the parser
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:
// Default
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->relkind)
{
case OBJECT_TABLE:
appendStringInfoString(str, "TABLE ");
break;
case OBJECT_MATVIEW:
appendStringInfoString(str, "MATERIALIZED VIEW ");
break;
default:
// Not supported here
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:
// Default
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:
// Other object types are not supported here in the parser
Assert(false);
}
if (drop_stmt->concurrent)
appendStringInfoString(str, "CONCURRENTLY ");
if (drop_stmt->missing_ok)
appendStringInfoString(str, "IF EXISTS ");
switch (drop_stmt->removeType)
{
// drop_type_any_name
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;
// drop_type_name
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;
// drop_type_name_on_any_name
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:
deparseStringLiteral(str, strVal(linitial(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:
// Not present in raw parse trees
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:
// No other object types supported here
Assert(false);
}
appendStringInfoChar(str, ' ');
if (alter_object_depends_stmt->remove)
appendStringInfoString(str, "NO ");
appendStringInfoString(str, "DEPENDS ON EXTENSION ");
deparseColId(str, strVal(alter_object_depends_stmt->extname));
}
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: /* add column */
if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "ADD ATTRIBUTE ");
else
appendStringInfoString(str, "ADD COLUMN ");
break;
case AT_AddColumnRecurse: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_AddColumnToView: /* implicitly via CREATE OR REPLACE VIEW */
// Not present in raw parser output
Assert(false);
break;
case AT_ColumnDefault: /* alter column default */
appendStringInfoString(str, "ALTER COLUMN ");
if (alter_table_cmd->def != NULL)
options = "SET DEFAULT";
else
options = "DROP DEFAULT";
break;
case AT_CookedColumnDefault: /* add a pre-cooked column default */
// Not present in raw parser output
Assert(false);
break;
case AT_DropNotNull: /* alter column drop not null */
appendStringInfoString(str, "ALTER COLUMN ");
options = "DROP NOT NULL";
break;
case AT_SetNotNull: /* alter column set not null */
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET NOT NULL";
break;
case AT_DropExpression: /* alter column drop expression */
appendStringInfoString(str, "ALTER COLUMN ");
options = "DROP EXPRESSION";
trailing_missing_ok = true;
break;
case AT_CheckNotNull: /* check column is already marked not null */
// Not present in raw parser output
Assert(false);
break;
case AT_SetStatistics: /* alter column set statistics */
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET STATISTICS";
break;
case AT_SetOptions: /* alter column set ( options ) */
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET";
break;
case AT_ResetOptions: /* alter column reset ( options ) */
appendStringInfoString(str, "ALTER COLUMN ");
options = "RESET";
break;
case AT_SetStorage: /* alter column set storage */
appendStringInfoString(str, "ALTER COLUMN ");
options = "SET STORAGE";
break;
case AT_DropColumn: /* drop column */
if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "DROP ATTRIBUTE ");
else
appendStringInfoString(str, "DROP ");
break;
case AT_DropColumnRecurse: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_AddIndex: /* add index */
appendStringInfoString(str, "ADD INDEX ");
break;
case AT_ReAddIndex: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_AddConstraint: /* add constraint */
appendStringInfoString(str, "ADD ");
break;
case AT_AddConstraintRecurse: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_ReAddConstraint: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_ReAddDomainConstraint: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_AlterConstraint: /* alter constraint */
appendStringInfoString(str, "ALTER "); // CONSTRAINT keyword gets added by the Constraint itself (when deparsing def)
break;
case AT_ValidateConstraint: /* validate constraint */
appendStringInfoString(str, "VALIDATE CONSTRAINT ");
break;
case AT_ValidateConstraintRecurse: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_AddIndexConstraint: /* add constraint using existing index */
// Not present in raw parser output
Assert(false);
break;
case AT_DropConstraint: /* drop constraint */
appendStringInfoString(str, "DROP CONSTRAINT ");
break;
case AT_DropConstraintRecurse: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_ReAddComment: /* internal to commands/tablecmds.c */
Assert(false);
break;
case AT_AlterColumnType: /* alter column type */
if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
appendStringInfoString(str, "ALTER ATTRIBUTE ");
else
appendStringInfoString(str, "ALTER COLUMN ");
options = "TYPE";
break;
case AT_AlterColumnGenericOptions: /* alter column OPTIONS (...) */
appendStringInfoString(str, "ALTER COLUMN ");
// Handled via special case in def handling
break;
case AT_ChangeOwner: /* change owner */
appendStringInfoString(str, "OWNER TO ");
deparseRoleSpec(str, alter_table_cmd->newowner);
break;
case AT_ClusterOn: /* CLUSTER ON */
appendStringInfoString(str, "CLUSTER ON ");
break;
case AT_DropCluster: /* SET WITHOUT CLUSTER */
appendStringInfoString(str, "SET WITHOUT CLUSTER ");
break;
case AT_SetLogged: /* SET LOGGED */
appendStringInfoString(str, "SET LOGGED ");
break;
case AT_SetUnLogged: /* SET UNLOGGED */
appendStringInfoString(str, "SET UNLOGGED ");
break;
case AT_DropOids: /* SET WITHOUT OIDS */
appendStringInfoString(str, "SET WITHOUT OIDS ");
break;
case AT_SetTableSpace: /* SET TABLESPACE */
appendStringInfoString(str, "SET TABLESPACE ");
break;
case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
appendStringInfoString(str, "SET ");
break;
case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
appendStringInfoString(str, "RESET ");
break;
case AT_ReplaceRelOptions: /* replace reloption list in its entirety */
// Not present in raw parser output
Assert(false);
break;
case AT_EnableTrig: /* ENABLE TRIGGER name */
appendStringInfoString(str, "ENABLE TRIGGER ");
break;
case AT_EnableAlwaysTrig: /* ENABLE ALWAYS TRIGGER name */
appendStringInfoString(str, "ENABLE ALWAYS TRIGGER ");
break;
case AT_EnableReplicaTrig: /* ENABLE REPLICA TRIGGER name */
appendStringInfoString(str, "ENABLE REPLICA TRIGGER ");
break;
case AT_DisableTrig: /* DISABLE TRIGGER name */
appendStringInfoString(str, "DISABLE TRIGGER ");
break;
case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
appendStringInfoString(str, "ENABLE TRIGGER ");
break;
case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
appendStringInfoString(str, "DISABLE TRIGGER ALL ");
break;
case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
appendStringInfoString(str, "ENABLE TRIGGER USER ");
break;
case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
appendStringInfoString(str, "DISABLE TRIGGER USER ");
break;
case AT_EnableRule: /* ENABLE RULE name */
appendStringInfoString(str, "ENABLE RULE ");
break;
case AT_EnableAlwaysRule: /* ENABLE ALWAYS RULE name */
appendStringInfoString(str, "ENABLE ALWAYS RULE ");
break;
case AT_EnableReplicaRule: /* ENABLE REPLICA RULE name */
appendStringInfoString(str, "ENABLE REPLICA RULE ");
break;
case AT_DisableRule: /* DISABLE RULE name */
appendStringInfoString(str, "DISABLE RULE ");
break;
case AT_AddInherit: /* INHERIT parent */
appendStringInfoString(str, "INHERIT ");
break;
case AT_DropInherit: /* NO INHERIT parent */
appendStringInfoString(str, "NO INHERIT ");
break;
case AT_AddOf: /* OF <type_name> */
appendStringInfoString(str, "OF ");
break;
case AT_DropOf: /* NOT OF */
appendStringInfoString(str, "NOT OF ");
break;
case AT_ReplicaIdentity: /* REPLICA IDENTITY */
appendStringInfoString(str, "REPLICA IDENTITY ");
break;
case AT_EnableRowSecurity: /* ENABLE ROW SECURITY */
appendStringInfoString(str, "ENABLE ROW LEVEL SECURITY ");
break;
case AT_DisableRowSecurity: /* DISABLE ROW SECURITY */
appendStringInfoString(str, "DISABLE ROW LEVEL SECURITY ");
break;
case AT_ForceRowSecurity: /* FORCE ROW SECURITY */
appendStringInfoString(str, "FORCE ROW LEVEL SECURITY ");
break;
case AT_NoForceRowSecurity: /* NO FORCE ROW SECURITY */
appendStringInfoString(str, "NO FORCE ROW LEVEL SECURITY ");
break;
case AT_GenericOptions: /* OPTIONS (...) */
// Handled in def field handling
break;
case AT_AttachPartition: /* ATTACH PARTITION */
appendStringInfoString(str, "ATTACH PARTITION ");
break;
case AT_DetachPartition: /* DETACH PARTITION */
appendStringInfoString(str, "DETACH PARTITION ");
break;
case AT_AddIdentity: /* ADD IDENTITY */
appendStringInfoString(str, "ALTER ");
options = "ADD";
// Other details are output via the constraint node (in def field)
break;
case AT_SetIdentity: /* SET identity column options */
appendStringInfoString(str, "ALTER ");
break;
case AT_DropIdentity: /* DROP IDENTITY */
appendStringInfoString(str, "ALTER COLUMN ");
options = "DROP IDENTITY";
trailing_missing_ok = true;
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, ' ');
}
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_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);
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_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;
default:
Assert(alter_table_cmd->def == NULL);
break;
}
deparseOptDropBehavior(str, alter_table_cmd->behavior);
removeTrailingSpace(str);
}
static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
{
ListCell *lc;
DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
appendStringInfoString(str, "ALTER ");
switch (alter_table_stmt->relkind)
{
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 ");
context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
break;
default:
Assert(false);
break;
}
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);
}
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:
// No other subtypes supported by the parser
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 void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
{
ListCell *lc;
switch (variable_set_stmt->kind)
{
case VAR_SET_VALUE: /* SET var = value */
appendStringInfoString(str, "SET ");
if (variable_set_stmt->is_local)
appendStringInfoString(str, "LOCAL ");
deparseVarName(str, variable_set_stmt->name);
appendStringInfoString(str, " TO ");
deparseVarList(str, variable_set_stmt->args);
break;
case VAR_SET_DEFAULT: /* SET var TO 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: /* SET var FROM 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: /* special case for SET TRANSACTION ... */
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: /* RESET var */
appendStringInfoString(str, "RESET ");
deparseVarName(str, variable_set_stmt->name);
break;
case VAR_RESET_ALL: /* 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); // Currently there are other supported values
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 ");
if (list_length(vacuum_stmt->options) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, vacuum_stmt->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, (Value *) def_elem->arg);
else if (IsA(def_elem->arg, String))
deparseOptBooleanOrString(str, strVal(def_elem->arg));
else
Assert(false);
}
if (lnext(vacuum_stmt->options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
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 ");
if (list_length(explain_stmt->options) > 0)
{
appendStringInfoChar(str, '(');
foreach(lc, explain_stmt->options)
{
DefElem *def_elem = castNode(DefElem, lfirst(lc));
deparseGenericDefElemName(str, def_elem->defname);
if (def_elem->arg != NULL && IsA(def_elem->arg, String))
{
appendStringInfoChar(str, ' ');
deparseOptBooleanOrString(str, strVal(def_elem->arg));
}
else if (def_elem->arg != NULL && (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float)))
{
appendStringInfoChar(str, ' ');
deparseNumericOnly(str, (Value *) def_elem->arg);
}
if (lnext(explain_stmt->options, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoString(str, ") ");
}
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)
{
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
Assert(false);
}
else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
{
appendStringInfoString(str, "FREEZE");
if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
appendStringInfoString(str, " 1");
}
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 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
{
appendStringInfoString(str, "HEADER");
if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
appendStringInfoString(str, " 1");
}
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 (");
deparseColumnList(str, castNode(List, def_elem->arg));
appendStringInfoChar(str, ')');
}
else if (strcmp(def_elem->defname, "force_null") == 0)
{
appendStringInfoString(str, "FORCE_NULL (");
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)
{
// Nothing
}
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, (Value *) 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:
// This shouldn't happen
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:
// No other object types are supported here in the parser
Assert(false);
break;
}
switch (alter_extension_contents_stmt->objtype)
{
// any_name
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;
// name
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);
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 ");
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->admin_opt)
appendStringInfoString(str, "WITH ADMIN OPTION ");
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, 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, ") ");
}
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");
}
// "AlterOptRoleElem" in gram.y
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 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "SUPERUSER");
}
else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOSUPERUSER");
}
else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "CREATEROLE");
}
else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOCREATEROLE");
}
else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "REPLICATION");
}
else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOREPLICATION");
}
else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "CREATEDB");
}
else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOCREATEDB");
}
else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "LOGIN");
}
else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOLOGIN");
}
else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "BYPASSRLS");
}
else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOBYPASSRLS");
}
else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 1)
{
appendStringInfoString(str, "INHERIT");
}
else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 0)
{
appendStringInfoString(str, "NOINHERIT");
}
else
{
Assert(false);
}
}
// "CreateOptRoleElem" in gram.y
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)
{
// Default
}
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, 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
{
// No other DefElems are supported
Assert(false);
}
}
deparseGrantStmt(str, alter_default_privileges_stmt->action);
}
static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
{
appendStringInfoString(str, "REINDEX ");
if (reindex_stmt->options & REINDEXOPT_VERBOSE)
appendStringInfoString(str, "(VERBOSE) ");
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->concurrent)
appendStringInfoString(str, "CONCURRENTLY ");
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:
// Not supported here
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;
}
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:
// Not supported here
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); // Default
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);
appendStringInfoString(str, ") ");
}
if (create_policy_stmt->with_check != NULL)
{
appendStringInfoString(str, "WITH CHECK (");
deparseExpr(str, create_policy_stmt->with_check);
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);
appendStringInfoString(str, ") ");
}
if (alter_policy_stmt->with_check != NULL)
{
appendStringInfoString(str, "WITH CHECK (");
deparseExpr(str, alter_policy_stmt->with_check);
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 ");
deparseStringLiteral(str, create_table_space_stmt->location);
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 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->tables) > 0)
{
appendStringInfoString(str, "FOR TABLE ");
deparseRelationExprList(str, create_publication_stmt->tables);
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->tables) > 0)
{
switch (alter_publication_stmt->tableAction)
{
case DEFELEM_SET:
appendStringInfoString(str, "SET TABLE ");
break;
case DEFELEM_ADD:
appendStringInfoString(str, "ADD TABLE ");
break;
case DEFELEM_DROP:
appendStringInfoString(str, "DROP TABLE ");
break;
case DEFELEM_UNSPEC:
Assert(false);
break;
}
deparseRelationExprList(str, alter_publication_stmt->tables);
}
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:
// No other cases are supported in the parser
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, (Value *) 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:
// No other cases are supported in the parser
Assert(false);
break;
}
appendStringInfoString(str, " IS ");
if (comment_stmt->comment != NULL)
deparseStringLiteral(str, comment_stmt->comment);
else
appendStringInfoString(str, "NULL");
}
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 ");
deparseExprList(str, create_stats_stmt->exprs);
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, ' ');
appendStringInfo(str, "SET STATISTICS %d", alter_stats_stmt->stxstattarget);
}
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, "SESSION ALL");
else
appendStringInfoString(str, 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);
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_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_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 (intVal(defelem->arg) == 1)
{
appendStringInfoString(str, " ENABLE ");
}
else if (intVal(defelem->arg) == 0)
{
appendStringInfoString(str, " DISABLE ");
}
else
{
Assert(false);
}
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);
}
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, (Value *) 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);
}
// "operator_def_list" in gram.y
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 deparseCurrentOfExpr(StringInfo str, CurrentOfExpr *current_of_expr)
{
appendStringInfoString(str, "CURRENT OF ");
appendStringInfoString(str, quote_identifier(current_of_expr->cursor_name));
}
static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_stmt)
{
ListCell *lc;
bool skip_events_or = true;
appendStringInfoString(str, "CREATE ");
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);
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)
{
switch (xml_expr->op)
{
case IS_XMLCONCAT: /* XMLCONCAT(args) */
appendStringInfoString(str, "xmlconcat(");
deparseExprList(str, xml_expr->args);
appendStringInfoChar(str, ')');
break;
case IS_XMLELEMENT: /* XMLELEMENT(name, xml_attributes, args) */
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: /* XMLFOREST(xml_attributes) */
appendStringInfoString(str, "xmlforest(");
deparseXmlAttributeList(str, xml_expr->named_args);
appendStringInfoChar(str, ')');
break;
case IS_XMLPARSE: /* XMLPARSE(text, is_doc, preserve_ws) */
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));
if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
appendStringInfoString(str, " PRESERVE WHITESPACE");
appendStringInfoChar(str, ')');
break;
case IS_XMLPI: /* XMLPI(name [, args]) */
appendStringInfoString(str, "xmlpi(name ");
appendStringInfoString(str, quote_identifier(xml_expr->name));
if (xml_expr->args != NULL)
{
appendStringInfoString(str, ", ");
deparseExpr(str, linitial(xml_expr->args));
}
appendStringInfoChar(str, ')');
break;
case IS_XMLROOT: /* XMLROOT(xml, version, standalone) */
appendStringInfoString(str, "xmlroot(");
deparseExpr(str, linitial(xml_expr->args));
appendStringInfoString(str, ", version ");
if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
appendStringInfoString(str, "NO VALUE");
else
deparseExpr(str, lsecond(xml_expr->args));
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: /* XMLSERIALIZE(is_document, xmlval) */
// These are represented as XmlSerialize in raw parse trees
Assert(false);
break;
case IS_DOCUMENT: /* xmlval IS DOCUMENT */
Assert(list_length(xml_expr->args) == 1);
deparseExpr(str, linitial(xml_expr->args));
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);
appendStringInfoChar(str, ' ');
}
if (range_table_func_col->coldefexpr)
{
appendStringInfoString(str, "DEFAULT ");
deparseExpr(str, range_table_func_col->coldefexpr);
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);
appendStringInfoChar(str, ')');
appendStringInfoString(str, " PASSING ");
deparseExpr(str, range_table_func->docexpr);
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);
appendStringInfoString(str, " AS ");
deparseTypeName(str, xml_serialize->typeName);
appendStringInfoString(str, ")");
}
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 ");
if (cluster_stmt->options & CLUOPT_VERBOSE)
appendStringInfoString(str, "VERBOSE ");
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, Value *value, DeparseNodeContext context)
{
switch (nodeTag(value))
{
case T_Integer:
case T_Float:
deparseNumericOnly(str, value);
break;
case T_String:
if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
appendStringInfoString(str, quote_identifier(value->val.str));
} else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
deparseStringLiteral(str, value->val.str);
} else {
appendStringInfoString(str, value->val.str);
}
break;
case T_BitString:
if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
{
appendStringInfoChar(str, 'x');
deparseStringLiteral(str, value->val.str + 1);
}
else if (strlen(value->val.str) >= 1 && value->val.str[0] == 'b')
{
appendStringInfoChar(str, 'b');
deparseStringLiteral(str, value->val.str + 1);
}
else
{
Assert(false);
}
break;
case T_Null:
appendStringInfoString(str, "NULL");
break;
default:
elog(ERROR, "unrecognized value node type: %d",
(int) nodeTag(value));
break;
}
}
// "PrepareableStmt" in gram.y
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;
default:
Assert(false);
}
}
// "RuleActionStmt" in gram.y
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);
}
}
// "ExplainableStmt" in gram.y
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;
default:
Assert(false);
}
}
// "schema_stmt" in gram.y
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);
}
}
// "stmt" in gram.y
static void deparseStmt(StringInfo str, Node *node)
{
// Note the following grammar names are missing in the list, because they
// get mapped to other node types:
//
// - AlterForeignTableStmt (=> AlterTableStmt)
// - AlterGroupStmt (=> AlterRoleStmt)
// - AlterCompositeTypeStmt (=> AlterTableStmt)
// - AnalyzeStmt (=> VacuumStmt)
// - CreateGroupStmt (=> CreateRoleStmt)
// - CreateMatViewStmt (=> CreateTableAsStmt)
// - CreateUserStmt (=> CreateRoleStmt)
// - DropCastStmt (=> DropStmt)
// - DropOpClassStmt (=> DropStmt)
// - DropOpFamilyStmt (=> DropStmt)
// - DropPLangStmt (=> DropPLangStmt)
// - DropTransformStmt (=> DropStmt)
// - RemoveAggrStmt (=> DropStmt)
// - RemoveFuncStmt (=> DropStmt)
// - RemoveOperStmt (=> DropStmt)
// - RevokeStmt (=> GrantStmt)
// - RevokeRoleStmt (=> GrantRoleStmt)
// - VariableResetStmt (=> VariableSetStmt)
//
// And the following grammar names error out in the parser:
// - CreateAssertionStmt (not supported yet)
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_AlterTableStmt:
deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
break;
case T_AlterTableSpaceOptionsStmt: // "AlterTblSpcStmt" in gram.y
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: // "CreateAsStmt" in gram.y
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_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;
// These node types are created by DefineStmt grammar for CREATE TYPE in some cases
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:
// No other node types are supported at the top-level
Assert(false);
}
}
PgQueryDeparseResult pg_query_deparse_protobuf(PgQueryProtobuf parse_tree)
{
PgQueryDeparseResult result = {0};
StringInfoData str;
MemoryContext ctx;
List *stmts;
ListCell *lc;
ctx = pg_query_enter_memory_context();
PG_TRY();
{
stmts = pg_query_protobuf_to_nodes(parse_tree);
initStringInfo(&str);
foreach(lc, stmts) {
deparseRawStmt(&str, castNode(RawStmt, lfirst(lc)));
if (lnext(stmts, lc))
appendStringInfoString(&str, "; ");
}
result.query = strdup(str.data);
}
PG_CATCH();
{
ErrorData* error_data;
PgQueryError* error;
MemoryContextSwitchTo(ctx);
error_data = CopyErrorData();
// Note: This is intentionally malloc so exiting the memory context doesn't free this
error = malloc(sizeof(PgQueryError));
error->message = strdup(error_data->message);
error->filename = strdup(error_data->filename);
error->funcname = strdup(error_data->funcname);
error->context = NULL;
error->lineno = error_data->lineno;
error->cursorpos = error_data->cursorpos;
result.error = error;
FlushErrorState();
}
PG_END_TRY();
pg_query_exit_memory_context(ctx);
return result;
}
void pg_query_free_deparse_result(PgQueryDeparseResult result)
{
if (result.error) {
pg_query_free_error(result.error);
}
free(result.query);
}