0003-Code-restructuring-for-supporting-autogeneration-cod.patch
text/x-patch
Filename: 0003-Code-restructuring-for-supporting-autogeneration-cod.patch
Type: text/x-patch
Part: 4
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0003
Subject: Code restructuring for supporting autogeneration code for create/alter and drop commands.
| File | + | − |
|---|---|---|
| src/backend/commands/ddldeparse.c | 18 | 1605 |
| src/backend/nodes/ddldeparsefuncs.c | 1636 | 0 |
| src/backend/nodes/Makefile | 1 | 0 |
| src/backend/nodes/meson.build | 1 | 0 |
| src/include/tcop/ddldeparse.h | 41 | 1 |
From 04bc7f99433cf05c197f95b695f187f9242ac2f6 Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Tue, 27 Jun 2023 14:25:26 +0530
Subject: [PATCH 3/5] Code restructuring for supporting autogeneration code for
create/alter and drop commands.
Code restructuring for supporting autogeneration code for create/alter
and drop commands.
---
src/backend/commands/ddldeparse.c | 1623 +-------------------------
src/backend/nodes/Makefile | 1 +
src/backend/nodes/ddldeparsefuncs.c | 1636 +++++++++++++++++++++++++++
src/backend/nodes/meson.build | 1 +
src/include/tcop/ddldeparse.h | 42 +-
5 files changed, 1697 insertions(+), 1606 deletions(-)
create mode 100644 src/backend/nodes/ddldeparsefuncs.c
diff --git a/src/backend/commands/ddldeparse.c b/src/backend/commands/ddldeparse.c
index faaf0de3f9..3b1fe36a02 100644
--- a/src/backend/commands/ddldeparse.c
+++ b/src/backend/commands/ddldeparse.c
@@ -69,7 +69,7 @@
/*
* Return the string representation of the given RELPERSISTENCE value.
*/
-static char *
+char *
get_persistence_str(char persistence)
{
switch (persistence)
@@ -93,7 +93,7 @@ get_persistence_str(char persistence)
* Caller must have set a correct deparse context and must ensure that the
* passed attribute has a default value.
*/
-static char *
+char *
RelationGetColumnDefault(Relation rel, AttrNumber attno, List *dpcontext)
{
Node *defval;
@@ -110,7 +110,7 @@ RelationGetColumnDefault(Relation rel, AttrNumber attno, List *dpcontext)
/*
* Obtain the deparsed partition bound expression for the given table.
*/
-static char *
+char *
RelationGetPartitionBound(Oid relid)
{
Datum deparsed;
@@ -138,7 +138,7 @@ RelationGetPartitionBound(Oid relid)
/*
* Insert JsonbValue key to the output parse state.
*/
-static void
+void
insert_jsonb_key(JsonbParseState *state, char *name)
{
JsonbValue key;
@@ -170,7 +170,7 @@ insert_jsonb_key(JsonbParseState *state, char *name)
* b) The caller need to carefully pass sets of arguments, we don't have the
* luxury of sprintf-like compiler warnings for malformed argument lists.
*/
-static void
+void
new_jsonb_VA(JsonbParseState *state, int numobjs,...)
{
va_list args;
@@ -241,7 +241,7 @@ new_jsonb_VA(JsonbParseState *state, int numobjs,...)
/*
* A helper routine to insert jsonb for typId to the output parse state.
*/
-static void
+void
new_jsonb_for_type(JsonbParseState *state, char *parentKey,
Oid typId, int32 typmod)
{
@@ -311,7 +311,7 @@ new_jsonb_for_qualname(JsonbParseState *state, Oid nspid, char *objName,
* A helper routine to set up name: 'schemaname, objname' where the object is
* specified by classId and objId.
*/
-static void
+void
new_jsonb_for_qualname_id(JsonbParseState *state, Oid classId, Oid objectId,
char *keyName, bool createObject)
{
@@ -353,7 +353,7 @@ new_jsonb_for_qualname_id(JsonbParseState *state, Oid classId, Oid objectId,
* A helper routine to insert key:value where value is array of qualname to
* the output parse state.
*/
-static void
+void
new_jsonbArray_for_qualname_id(JsonbParseState *state,
char *keyname, List *array)
{
@@ -376,7 +376,7 @@ new_jsonbArray_for_qualname_id(JsonbParseState *state,
* A helper routine to insert collate object for column
* definition to the output parse state.
*/
-static void
+void
insert_collate_object(JsonbParseState *state, char *parentKey, char *fmt,
Oid classId, Oid objectId, char *key)
{
@@ -400,7 +400,7 @@ insert_collate_object(JsonbParseState *state, char *parentKey, char *fmt,
* A helper routine to insert identity object for the table definition
* to the output parse state.
*/
-static void
+void
insert_identity_object(JsonbParseState *state, Oid nspid, char *relname)
{
new_jsonb_for_qualname(state, nspid, relname, "identity", true);
@@ -687,7 +687,7 @@ deparse_Seq_As_toJsonb(JsonbParseState *state, Form_pg_sequence seqdata)
* OR
* GENERATED %{option}s AS IDENTITY %{identity_type}s ( %{seq_definition: }s )
*/
-static void
+void
deparse_ColumnIdentity_toJsonb(JsonbParseState *state, char *parentKey,
Oid seqrelid, char identity, bool alter_table)
{
@@ -769,7 +769,7 @@ deparse_ColumnIdentity_toJsonb(JsonbParseState *state, char *parentKey,
* "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s
* %{not_null}s %{default}s %{identity_column}s %{generated_column}s"
*/
-static void
+void
deparse_ColumnDef_toJsonb(JsonbParseState *state, Relation relation,
List *dpcontext, bool composite, ColumnDef *coldef,
bool is_alter)
@@ -1267,7 +1267,7 @@ deparse_TableElems_ToJsonb(JsonbParseState *state, Relation relation,
* Given a table OID, return a schema-qualified table list representing
* the parent tables.
*/
-static List *
+List *
deparse_InhRels_ToJsonb(Oid objectId)
{
List *parents = NIL;
@@ -1425,7 +1425,7 @@ deparse_Constraints_ToJsonb(JsonbParseState *state, Oid relationId)
* Insert columns and constraints elements in output JsonbParseState
* Returns true if elements are inserted
*/
-static bool
+bool
add_table_elems_if_any(JsonbParseState *state, StringInfo fmtStr,
Relation relation, List *tableElts, List *dpcontext,
Oid objectId, bool typed, bool composite)
@@ -1521,7 +1521,7 @@ deparse_DefElem_ToJsonb(JsonbParseState *state, DefElem *elem, bool is_reset)
* Verbose syntax
* ALTER COLUMN %{column}I RESET|SET (%{options:, }s)
*/
-static void
+void
deparse_ColumnSetOptions_ToJsonb(JsonbParseState *state, AlterTableCmd *subcmd)
{
ListCell *cell;
@@ -1564,7 +1564,7 @@ deparse_ColumnSetOptions_ToJsonb(JsonbParseState *state, AlterTableCmd *subcmd)
* Verbose syntax
* RESET|SET (%{options:, }s)
*/
-static void
+void
deparse_RelSetOptions_toJsonb(JsonbParseState *state, AlterTableCmd *subcmd)
{
ListCell *cell;
@@ -1604,7 +1604,7 @@ deparse_RelSetOptions_toJsonb(JsonbParseState *state, AlterTableCmd *subcmd)
/*
* Deparse WITH clause, as used by Create Table.
*/
-static void
+void
deparse_withObj_ToJsonb(JsonbParseState *state, CreateStmt *node)
{
ListCell *cell;
@@ -1625,1593 +1625,6 @@ deparse_withObj_ToJsonb(JsonbParseState *state, CreateStmt *node)
pushJsonbValue(&state, WJB_END_ARRAY, NULL);
}
-/*
- * Deparse a CreateStmt (CREATE TABLE).
- *
- * Given a table OID and the parse tree that created it, return JsonbValue
- * representing the creation command.
- *
- * Verbose syntax
- * CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D [OF
- * %{of_type}T | PARTITION OF %{parent_identity}D] %{table_elements}s
- * %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s
- * %{tablespace}s
- */
-static Jsonb *
-deparse_CreateStmt(Oid objectId, Node *parsetree)
-{
- CreateStmt *node = (CreateStmt *) parsetree;
- Relation relation = relation_open(objectId, AccessShareLock);
- Oid nspid = relation->rd_rel->relnamespace;
- char *relname = RelationGetRelationName(relation);
- List *dpcontext;
- char *perstr;
- StringInfoData fmtStr;
- JsonbParseState *state = NULL;
- JsonbValue *value;
-
- initStringInfo(&fmtStr);
-
- /* mark the begin of ROOT object and start adding elements to it. */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- appendStringInfoString(&fmtStr, "CREATE");
-
- /* PERSISTENCE */
- perstr = get_persistence_str(relation->rd_rel->relpersistence);
- if (perstr)
- {
- appendStringInfoString(&fmtStr, " %{persistence}s");
- new_jsonb_VA(state, 1,
- "persistence", jbvString, perstr);
- }
-
- appendStringInfoString(&fmtStr, " TABLE");
-
- /* IF NOT EXISTS */
- if (node->if_not_exists)
- {
- appendStringInfoString(&fmtStr, " %{if_not_exists}s");
- new_jsonb_VA(state, 1,
- "if_not_exists", jbvString, "IF NOT EXISTS");
- }
-
- /* IDENTITY */
- appendStringInfoString(&fmtStr, " %{identity}D");
- insert_identity_object(state, nspid, relname);
-
- dpcontext = deparse_context_for(RelationGetRelationName(relation),
- objectId);
-
- /*
- * TABLE-ELEMENTS array creation
- *
- * Typed tables and partitions use a slightly different format string: we
- * must not put table_elements with parents directly in the fmt string,
- * because if there are no options the parentheses must not be emitted;
- * and also, typed tables do not allow for inheritance.
- */
- if (node->ofTypename || node->partbound)
- {
- /* Insert the "of type" or "partition of" clause whichever present */
- if (node->ofTypename)
- {
- appendStringInfoString(&fmtStr, " OF %{of_type}T");
- new_jsonb_for_type(state, "of_type",
- relation->rd_rel->reloftype, -1);
- }
- else
- {
- List *parents;
- Oid objid;
-
- appendStringInfoString(&fmtStr, " PARTITION OF %{parent_identity}D");
- parents = deparse_InhRels_ToJsonb(objectId);
- objid = linitial_oid(parents);
- Assert(list_length(parents) == 1);
- new_jsonb_for_qualname_id(state, RelationRelationId,
- objid, "parent_identity", true);
- }
-
- /*
- * We can't put table elements directly in the fmt string as an array
- * surrounded by parentheses here, because an empty clause would cause
- * a syntax error. Therefore, we first check the presence and then add
- * the elements.
- */
- add_table_elems_if_any(state, &fmtStr, relation,
- node->tableElts, dpcontext, objectId,
- true, /* typed table */
- false); /* not composite */
- }
- else
- {
- List *inhrelations;
- bool telems_present = false;
-
- /*
- * There is no need to process LIKE clauses separately; they have
- * already been transformed into columns and constraints.
- */
-
- /* Check if table elements are present, if so, add them. */
- telems_present = add_table_elems_if_any(state, &fmtStr, relation,
- node->tableElts, dpcontext, objectId,
- false, /* not typed table */
- false); /* not composite */
-
- /*
- * If no table elements added, then add empty "()" needed for
- * 'inherit' create table syntax. Example: CREATE TABLE t1 () INHERITS
- * (t0);
- */
- if (!telems_present)
- appendStringInfoString(&fmtStr, " ()");
-
- /*
- * Add inheritance specification. We cannot simply scan the list of
- * parents from the parser node, because that may lack the actual
- * qualified names of the parent relations. Rather than trying to
- * re-resolve them from the information in the parse node, it seems
- * more accurate and convenient to grab it from pg_inherits.
- */
- if (node->inhRelations != NIL)
- {
- appendStringInfoString(&fmtStr, " %{inherits}s");
- insert_jsonb_key(state, "inherits");
-
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- new_jsonb_VA(state, 1, "fmt", jbvString, "INHERITS (%{parents:, }D)");
- inhrelations = deparse_InhRels_ToJsonb(objectId);
-
- new_jsonbArray_for_qualname_id(state, "parents", inhrelations);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
- }
-
- /* FOR VALUES clause */
- if (node->partbound)
- {
- appendStringInfoString(&fmtStr, " %{partition_bound}s");
-
- /*
- * Get pg_class.relpartbound. We cannot use partbound in the parsetree
- * directly as it's the original partbound expression which haven't
- * been transformed.
- */
- new_jsonb_VA(state, 1,
- "partition_bound", jbvString,
- RelationGetPartitionBound(objectId));
- }
-
- /* PARTITION BY clause */
- if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- {
- appendStringInfoString(&fmtStr, " %{partition_by}s");
- insert_jsonb_key(state, "partition_by");
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "PARTITION BY %{definition}s",
- "definition", jbvString,
- pg_get_partkeydef_string(objectId));
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
-
- /* USING clause */
- if (node->accessMethod)
- {
- appendStringInfoString(&fmtStr, " %{access_method}s");
- insert_jsonb_key(state, "access_method");
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "USING %{access_method}I",
- "access_method", jbvString, node->accessMethod);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
-
- /* WITH clause */
- if (node->options)
- {
- appendStringInfoString(&fmtStr, " %{with_clause}s");
- insert_jsonb_key(state, "with_clause");
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 1,
- "fmt", jbvString, "WITH (%{with:, }s)");
-
- deparse_withObj_ToJsonb(state, node);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- }
-
- /* TABLESPACE */
- if (node->tablespacename)
- {
- appendStringInfoString(&fmtStr, " %{tablespace}s");
- insert_jsonb_key(state, "tablespace");
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "TABLESPACE %{tablespace}I",
- "tablespace", jbvString, node->tablespacename);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
-
- relation_close(relation, AccessShareLock);
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtStr.data);
-
- pfree(fmtStr.data);
-
- /* Mark the end of ROOT object */
- value = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- return JsonbValueToJsonb(value);
-}
-
-/*
- * Deparse a DropStmt (DROP TABLE).
- *
- * Given an object identity and the parse tree that created it, return
- * jsonb string representing the drop command.
- *
- * Verbose syntax
- * DROP %{objtype}s %{concurrently}s %{if_exists}s %{objidentity}s %{cascade}s
- */
-char *
-deparse_drop_table(const char *objidentity, const char *objecttype,
- Node *parsetree)
-{
- DropStmt *node = (DropStmt *) parsetree;
- StringInfoData fmtStr;
- JsonbValue *jsonbval;
- Jsonb *jsonb;
- StringInfoData str;
- JsonbParseState *state = NULL;
-
- initStringInfo(&str);
- initStringInfo(&fmtStr);
-
- /* mark the begin of ROOT object and start adding elements to it. */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- /* Start constructing fmt string */
- appendStringInfoString(&fmtStr, "DROP %{objtype}s");
-
- /* OBJTYPE */
- new_jsonb_VA(state, 1, "objtype", jbvString, objecttype);
-
- /* CONCURRENTLY */
- if (node->concurrent)
- {
- appendStringInfoString(&fmtStr, " %{concurrently}s");
- new_jsonb_VA(state, 1,
- "concurrently", jbvString, "CONCURRENTLY");
- }
-
- /* IF EXISTS */
- if (node->missing_ok)
- {
- appendStringInfoString(&fmtStr, " %{if_exists}s");
- new_jsonb_VA(state, 1, "if_exists", jbvString, "IF EXISTS");
- }
-
- /* IDENTITY */
- appendStringInfoString(&fmtStr, " %{objidentity}s");
- new_jsonb_VA(state, 1, "objidentity", jbvString, objidentity);
-
- /* CASCADE */
- if (node->behavior == DROP_CASCADE)
- {
- appendStringInfoString(&fmtStr, " %{cascade}s");
- new_jsonb_VA(state, 1, "cascade", jbvString, "CASCADE");
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtStr.data);
- pfree(fmtStr.data);
-
- jsonbval = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- jsonb = JsonbValueToJsonb(jsonbval);
- return JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
-}
-
-/*
- * Deparse all the collected subcommands and return jsonb string representing
- * the alter command.
- *
- * Verbose syntax
- * ALTER %{objtype}s %{only}s %{identity}D %{subcmds:, }s
- */
-static Jsonb *
-deparse_AlterTableStmt(CollectedCommand *cmd)
-{
- List *dpcontext;
- Relation rel;
- ListCell *cell;
- const char *reltype;
- Oid relId = cmd->d.alterTable.objectId;
- AlterTableStmt *stmt = NULL;
- StringInfoData fmtStr;
- JsonbParseState *state = NULL;
- bool subCmdArray = false;
- JsonbValue *value;
-
- Assert(cmd->type == SCT_AlterTable);
- stmt = (AlterTableStmt *) cmd->parsetree;
-
- Assert(IsA(stmt, AlterTableStmt) || IsA(stmt, AlterTableMoveAllStmt));
-
- initStringInfo(&fmtStr);
-
- /*
- * ALTER TABLE subcommands generated for TableLikeClause is processed in
- * the top level CREATE TABLE command; return empty here.
- */
- if (IsA(stmt, AlterTableStmt) && stmt->table_like)
- return NULL;
-
- rel = relation_open(relId, AccessShareLock);
-
- switch (rel->rd_rel->relkind)
- {
- case RELKIND_RELATION:
- case RELKIND_PARTITIONED_TABLE:
- reltype = "TABLE";
- break;
- case RELKIND_INDEX:
- case RELKIND_PARTITIONED_INDEX:
- case RELKIND_VIEW:
- case RELKIND_COMPOSITE_TYPE:
- case RELKIND_FOREIGN_TABLE:
- case RELKIND_MATVIEW:
- /* unsupported relkind */
- table_close(rel, AccessShareLock);
- return NULL;
-
- default:
- elog(ERROR, "unexpected relkind %d", rel->rd_rel->relkind);
- }
-
-
- dpcontext = deparse_context_for(RelationGetRelationName(rel), relId);
-
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- /* Start constructing fmt string */
- appendStringInfoString(&fmtStr, "ALTER %{objtype}s");
-
- new_jsonb_VA(state, 1, "objtype", jbvString, reltype);
-
- if (!stmt->relation->inh)
- {
- appendStringInfoString(&fmtStr, " %{only}s");
- new_jsonb_VA(state, 1, "only", jbvString, "ONLY");
- }
-
- appendStringInfoString(&fmtStr, " %{identity}D");
- insert_identity_object(state, rel->rd_rel->relnamespace,
- RelationGetRelationName(rel));
-
- foreach(cell, cmd->d.alterTable.subcmds)
- {
- CollectedATSubcmd *sub = (CollectedATSubcmd *) lfirst(cell);
- AlterTableCmd *subcmd = (AlterTableCmd *) sub->parsetree;
-
- Assert(IsA(subcmd, AlterTableCmd));
-
- /*
- * Skip deparse of the subcommand if the objectId doesn't match the
- * target relation ID. It can happen for inherited tables when
- * subcommands for inherited tables and the parent table are both
- * collected in the ALTER TABLE command for the parent table.
- */
- if (subcmd->subtype != AT_AttachPartition &&
- sub->address.objectId != relId &&
- has_superclass(sub->address.objectId))
- continue;
-
- /* Mark the begin of subcmds array */
- if (!subCmdArray)
- {
- appendStringInfoString(&fmtStr, " %{subcmds:, }s");
- insert_jsonb_key(state, "subcmds");
- pushJsonbValue(&state, WJB_BEGIN_ARRAY, NULL);
- subCmdArray = true;
- }
-
- switch (subcmd->subtype)
- {
- case AT_AddColumn:
- {
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /* XXX need to set the "recurse" bit somewhere? */
- Assert(IsA(subcmd->def, ColumnDef));
-
- /*
- * Syntax: ADD COLUMN %{if_not_exists}s %{definition}s"
- * where definition: "%{name}I %{coltype}T STORAGE
- * %{colstorage}s %{compression}s %{collation}s
- * %{not_null}s %{default}s %{identity_column}s
- * %{generated_column}s"
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- appendStringInfoString(&fmtSub, "ADD COLUMN");
- new_jsonb_VA(state, 1, "type", jbvString, "add column");
-
- if (subcmd->missing_ok)
- {
- appendStringInfoString(&fmtSub, " %{if_not_exists}s");
- new_jsonb_VA(state, 1,
- "if_not_exists", jbvString, "IF NOT EXISTS");
- }
-
- /* Push definition key-value pair */
- appendStringInfoString(&fmtSub, " %{definition}s");
- insert_jsonb_key(state, "definition");
-
- deparse_ColumnDef_toJsonb(state, rel, dpcontext,
- false, (ColumnDef *) subcmd->def,
- true);
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
- }
-
- case AT_AddIndexConstraint:
- {
- IndexStmt *istmt;
- Relation idx;
- Oid conOid = sub->address.objectId;
-
- Assert(IsA(subcmd->def, IndexStmt));
- istmt = (IndexStmt *) subcmd->def;
-
- Assert(istmt->isconstraint && istmt->unique);
-
- idx = relation_open(istmt->indexOid, AccessShareLock);
-
- /*
- * Syntax: ADD CONSTRAINT %{name}I %{constraint_type}s
- * USING INDEX %index_name}I %{deferrable}s
- * %{init_deferred}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- new_jsonb_VA(state, 7,
- "fmt", jbvString,
- "ADD CONSTRAINT %{name}I %{constraint_type}s"
- " USING INDEX %{index_name}I %{deferrable}s"
- " %{init_deferred}s",
- "type", jbvString, "add constraint using index",
- "name", jbvString, get_constraint_name(conOid),
- "constraint_type", jbvString,
- istmt->primary ? "PRIMARY KEY" : "UNIQUE",
- "index_name", jbvString,
- RelationGetRelationName(idx),
- "deferrable", jbvString,
- istmt->deferrable ? "DEFERRABLE" :
- "NOT DEFERRABLE",
- "init_deferred", jbvString,
- istmt->initdeferred ? "INITIALLY DEFERRED" :
- "INITIALLY IMMEDIATE");
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- relation_close(idx, AccessShareLock);
- break;
- }
- case AT_ReAddIndex:
- case AT_ReAddConstraint:
- case AT_ReAddDomainConstraint:
- case AT_ReAddComment:
- case AT_ReplaceRelOptions:
- case AT_CheckNotNull:
- case AT_ReAddStatistics:
- /* Subtypes used for internal operations; nothing to do here */
- break;
-
- case AT_ColumnDefault:
- if (subcmd->def == NULL)
- {
- /*
- * Syntax: ALTER COLUMN %{column}I DROP DEFAULT
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I DROP DEFAULT",
- "type", jbvString, "drop default",
- "column", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
- else
- {
- List *dpcontext_rel;
- HeapTuple attrtup;
- AttrNumber attno;
-
- dpcontext_rel = deparse_context_for(
- RelationGetRelationName(rel),
- RelationGetRelid(rel));
- attrtup = SearchSysCacheAttName(RelationGetRelid(rel),
- subcmd->name);
- attno = ((Form_pg_attribute) GETSTRUCT(attrtup))->attnum;
-
- /*
- * Syntax: ALTER COLUMN %{column}I SET DEFAULT
- * %{definition}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- new_jsonb_VA(state, 4,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I SET DEFAULT"
- " %{definition}s",
- "type", jbvString, "set default",
- "column", jbvString, subcmd->name,
- "definition", jbvString,
- RelationGetColumnDefault(rel, attno,
- dpcontext_rel));
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- ReleaseSysCache(attrtup);
- }
-
- break;
-
- case AT_DropNotNull:
-
- /*
- * Syntax: ALTER COLUMN %{column}I DROP NOT NULL
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I DROP NOT NULL",
- "type", jbvString, "drop not null",
- "column", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_ForceRowSecurity:
-
- /*
- * Syntax: FORCE ROW LEVEL SECURITY
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 1, "fmt", jbvString,
- "FORCE ROW LEVEL SECURITY");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_NoForceRowSecurity:
-
- /*
- * Syntax: NO FORCE ROW LEVEL SECURITY
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 1, "fmt", jbvString,
- "NO FORCE ROW LEVEL SECURITY");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetNotNull:
-
- /*
- * Syntax: ALTER COLUMN %{column}I SET NOT NULL
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I SET NOT NULL",
- "type", jbvString, "set not null",
- "column", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DropExpression:
- {
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: ALTER COLUMN %{column}I DROP EXPRESSION
- * %{if_exists}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- appendStringInfoString(&fmtSub, "ALTER COLUMN"
- " %{column}I DROP EXPRESSION");
- new_jsonb_VA(state, 2,
- "type", jbvString, "drop expression",
- "column", jbvString, subcmd->name);
-
- if (subcmd->missing_ok)
- {
- appendStringInfoString(&fmtSub, " %{if_exists}s");
- new_jsonb_VA(state, 1,
- "if_exists", jbvString, "IF EXISTS");
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
- }
-
- case AT_SetStatistics:
- Assert(IsA(subcmd->def, Integer));
-
- /*
- * Syntax: ALTER COLUMN %{column}I SET STATISTICS
- * %{statistics}n
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 4,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I SET STATISTICS"
- " %{statistics}n",
- "type", jbvString, "set statistics",
- "column", jbvString, subcmd->name,
- "statistics", jbvNumeric,
- intVal((Integer *) subcmd->def));
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetOptions:
- case AT_ResetOptions:
-
- /*
- * Syntax: ALTER COLUMN %{column}I RESET|SET (%{options:, }s)
- */
- deparse_ColumnSetOptions_ToJsonb(state, subcmd);
- break;
-
- case AT_SetStorage:
- Assert(IsA(subcmd->def, String));
-
- /*
- * Syntax: ALTER COLUMN %{column}I SET STORAGE %{storage}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 4,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I SET STORAGE"
- " %{storage}s",
- "type", jbvString, "set storage",
- "column", jbvString, subcmd->name,
- "storage", jbvString,
- strVal((String *) subcmd->def));
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetCompression:
- Assert(IsA(subcmd->def, String));
-
- /*
- * Syntax: ALTER COLUMN %{column}I SET COMPRESSION
- * %{compression_method}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 4,
- "fmt", jbvString,
- "ALTER COLUMN %{column}I SET COMPRESSION"
- " %{compression_method}s",
- "type", jbvString, "set compression",
- "column", jbvString, subcmd->name,
- "compression_method", jbvString,
- strVal((String *) subcmd->def));
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DropColumn:
- {
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: DROP COLUMN %{if_exists}s %{column}I
- * %{cascade}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- appendStringInfoString(&fmtSub, "DROP COLUMN");
- new_jsonb_VA(state, 1, "type", jbvString, "drop column");
-
- if (subcmd->missing_ok)
- {
- appendStringInfoString(&fmtSub, " %{if_exists}s");
- new_jsonb_VA(state, 1,
- "if_exists", jbvString, "IF EXISTS");
- }
-
- appendStringInfoString(&fmtSub, " %{column}I");
- new_jsonb_VA(state, 1, "column", jbvString, subcmd->name);
-
- if (subcmd->behavior == DROP_CASCADE)
- {
- appendStringInfoString(&fmtSub, " %{cascade}s");
- new_jsonb_VA(state, 1,
- "cascade", jbvString, "CASCADE");
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- break;
- }
- case AT_AddIndex:
- {
- Oid idxOid = sub->address.objectId;
- IndexStmt *istmt PG_USED_FOR_ASSERTS_ONLY =
- (IndexStmt *) subcmd->def;
- Relation idx;
- const char *idxname;
- Oid constrOid;
-
- Assert(IsA(subcmd->def, IndexStmt));
- Assert(istmt->isconstraint);
-
- idx = relation_open(idxOid, AccessShareLock);
- idxname = RelationGetRelationName(idx);
-
- constrOid = get_relation_constraint_oid(
- cmd->d.alterTable.objectId,
- idxname, false);
-
- /*
- * Syntax: ADD CONSTRAINT %{name}I %{definition}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- new_jsonb_VA(state, 4,
- "fmt", jbvString,
- "ADD CONSTRAINT %{name}I %{definition}s",
- "type", jbvString, "add constraint",
- "name", jbvString, idxname,
- "definition", jbvString,
- pg_get_constraintdef_string(constrOid));
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- relation_close(idx, AccessShareLock);
- }
- break;
- case AT_AddConstraint:
- {
- /* XXX need to set the "recurse" bit somewhere? */
- Oid constrOid = sub->address.objectId;
-
- /* Skip adding constraint for inherits table sub command */
- if (!OidIsValid(constrOid))
- continue;
-
- Assert(IsA(subcmd->def, Constraint));
-
- /*
- * Syntax: ADD CONSTRAINT %{name}I %{definition}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 4,
- "fmt", jbvString,
- "ADD CONSTRAINT %{name}I %{definition}s",
- "type", jbvString, "add constraint",
- "name", jbvString, get_constraint_name(constrOid),
- "definition", jbvString,
- pg_get_constraintdef_string(constrOid));
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- break;
- }
-
- case AT_AlterConstraint:
- {
- Oid conOid = sub->address.objectId;
- Constraint *c = (Constraint *) subcmd->def;
-
- /* If no constraint was altered, silently skip it */
- if (!OidIsValid(conOid))
- break;
-
- Assert(IsA(c, Constraint));
-
- /*
- * Syntax: ALTER CONSTRAINT %{name}I %{deferrable}s
- * %{init_deferred}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 5,
- "fmt", jbvString,
- "ALTER CONSTRAINT %{name}I %{deferrable}s"
- " %{init_deferred}s",
- "type", jbvString, "alter constraint",
- "name", jbvString, get_constraint_name(conOid),
- "deferrable", jbvString,
- c->deferrable ? "DEFERRABLE" : "NOT DEFERRABLE",
- "init_deferred", jbvString,
- c->initdeferred ? "INITIALLY DEFERRED" :
- "INITIALLY IMMEDIATE");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
- break;
-
- case AT_ValidateConstraint:
-
- /*
- * Syntax: VALIDATE CONSTRAINT %{constraint}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "VALIDATE CONSTRAINT %{constraint}I",
- "type", jbvString, "validate constraint",
- "constraint", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DropConstraint:
- {
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: DROP CONSTRAINT %{if_exists}s %{constraint}I
- * %{cascade}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- appendStringInfoString(&fmtSub, "DROP CONSTRAINT");
- new_jsonb_VA(state, 1, "type", jbvString, "drop constraint");
-
- if (subcmd->missing_ok)
- {
- appendStringInfoString(&fmtSub, " %{if_exists}s");
- new_jsonb_VA(state, 1,
- "if_exists", jbvString, "IF EXISTS");
- }
-
- appendStringInfoString(&fmtSub, " %{constraint}I");
- new_jsonb_VA(state, 1,
- "constraint", jbvString, subcmd->name);
-
- if (subcmd->behavior == DROP_CASCADE)
- {
- appendStringInfoString(&fmtSub, " %{cascade}s");
- new_jsonb_VA(state, 1, "cascade", jbvString, "CASCADE");
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
- break;
-
- case AT_AlterColumnType:
- {
- TupleDesc tupdesc = RelationGetDescr(rel);
- Form_pg_attribute att;
- ColumnDef *def;
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- att = &(tupdesc->attrs[sub->address.objectSubId - 1]);
- def = (ColumnDef *) subcmd->def;
- Assert(IsA(def, ColumnDef));
-
- /*
- * Syntax: ALTER COLUMN %{column}I SET DATA TYPE
- * %{datatype}T %{collation}s %{using}s where using: USING
- * %{expression}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- appendStringInfoString(&fmtSub, "ALTER COLUMN %{column}I"
- " SET DATA TYPE %{datatype}T");
- new_jsonb_VA(state, 2,
- "type", jbvString, "alter column type",
- "column", jbvString, subcmd->name);
-
- new_jsonb_for_type(state, "datatype",
- att->atttypid, att->atttypmod);
-
- /* Add a COLLATE clause, if needed */
- if (OidIsValid(att->attcollation))
- {
- appendStringInfoString(&fmtSub, " %{collation}s");
- insert_collate_object(state, "collation",
- "COLLATE %{name}D",
- CollationRelationId,
- att->attcollation, "name");
- }
-
- /*
- * If there's a USING clause, transformAlterTableStmt ran
- * it through transformExpr and stored the resulting node
- * in cooked_default, which we can use here.
- */
- if (def->raw_default)
- {
- Datum deparsed;
- char *defexpr;
- List *exprs = NIL;
-
- exprs = lappend(exprs, def->cooked_default);
- defexpr = nodeToString(def->cooked_default);
- deparsed = DirectFunctionCall2(pg_get_expr,
- CStringGetTextDatum(defexpr),
- RelationGetRelid(rel));
- appendStringInfoString(&fmtSub, " %{using}s");
- insert_jsonb_key(state, "using");
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "USING %{expression}s",
- "expression", jbvString,
- TextDatumGetCString(deparsed));
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
-
- pfree(fmtSub.data);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
- break;
-
- case AT_ChangeOwner:
-
- /*
- * Syntax: OWNER TO %{owner}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "OWNER TO %{owner}I",
- "type", jbvString, "change owner",
- "owner", jbvString,
- get_rolespec_name(subcmd->newowner));
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_ClusterOn:
-
- /*
- * Syntax: CLUSTER ON %{index}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "CLUSTER ON %{index}I",
- "type", jbvString, "cluster on",
- "index", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
-
- case AT_DropCluster:
-
- /*
- * Syntax: SET WITHOUT CLUSTER
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "SET WITHOUT CLUSTER",
- "type", jbvString, "set without cluster");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetLogged:
-
- /*
- * Syntax: SET LOGGED
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "SET LOGGED",
- "type", jbvString, "set logged");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetUnLogged:
-
- /*
- * Syntax: SET UNLOGGED
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "SET UNLOGGED",
- "type", jbvString, "set unlogged");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DropOids:
-
- /*
- * Syntax: SET WITHOUT OIDS
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "SET WITHOUT OIDS",
- "type", jbvString, "set without oids");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetAccessMethod:
-
- /*
- * Syntax: SET ACCESS METHOD %{access_method}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "SET ACCESS METHOD %{access_method}I",
- "type", jbvString, "set access method",
- "access_method", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetTableSpace:
-
- /*
- * Syntax: SET TABLESPACE %{tablespace}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "SET TABLESPACE %{tablespace}I",
- "type", jbvString, "set tablespace",
- "tablespace", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_SetRelOptions:
- case AT_ResetRelOptions:
-
- /*
- * Syntax: SET|RESET (%{options:, }s)
- */
- deparse_RelSetOptions_toJsonb(state, subcmd);
- break;
-
- case AT_EnableTrig:
-
- /*
- * Syntax: ENABLE TRIGGER %{trigger}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "ENABLE TRIGGER %{trigger}I",
- "type", jbvString, "enable trigger",
- "trigger", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableAlwaysTrig:
-
- /*
- * Syntax: ENABLE ALWAYS TRIGGER %{trigger}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "ENABLE ALWAYS TRIGGER %{trigger}I",
- "type", jbvString, "enable always trigger",
- "trigger", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableReplicaTrig:
-
- /*
- * Syntax: ENABLE REPLICA TRIGGER %{trigger}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString,
- "ENABLE REPLICA TRIGGER %{trigger}I",
- "type", jbvString, "enable replica trigger",
- "trigger", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DisableTrig:
-
- /*
- * Syntax: DISABLE TRIGGER %{trigger}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "DISABLE TRIGGER %{trigger}I",
- "type", jbvString, "disable trigger",
- "trigger", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableTrigAll:
-
- /*
- * Syntax: ENABLE TRIGGER ALL
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "ENABLE TRIGGER ALL",
- "type", jbvString, "enable trigger all");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DisableTrigAll:
-
- /*
- * Syntax: DISABLE TRIGGER ALL
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "DISABLE TRIGGER ALL",
- "type", jbvString, "disable trigger all");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableTrigUser:
-
- /*
- * Syntax: ENABLE TRIGGER USER
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "ENABLE TRIGGER USER",
- "type", jbvString, "enable trigger user");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DisableTrigUser:
-
- /*
- * Syntax: DISABLE TRIGGER USER
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "DISABLE TRIGGER USER",
- "type", jbvString, "disable trigger user");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableRule:
-
- /*
- * Syntax: ENABLE RULE %{rule}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "ENABLE RULE %{rule}I",
- "type", jbvString, "enable rule",
- "rule", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableAlwaysRule:
-
- /*
- * Syntax: ENABLE ALWAYS RULE %{rule}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "ENABLE ALWAYS RULE %{rule}I",
- "type", jbvString, "enable always rule",
- "rule", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableReplicaRule:
-
- /*
- * Syntax: ENABLE REPLICA RULE %{rule}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "ENABLE REPLICA RULE %{rule}I",
- "type", jbvString, "enable replica rule",
- "rule", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DisableRule:
-
- /*
- * Syntax: DISABLE RULE %{rule}I
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 3,
- "fmt", jbvString, "DISABLE RULE %{rule}I",
- "type", jbvString, "disable rule",
- "rule", jbvString, subcmd->name);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_AddInherit:
-
- /*
- * Syntax: INHERIT %{parent}D
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "INHERIT %{parent}D",
- "type", jbvString, "inherit");
- new_jsonb_for_qualname_id(state, RelationRelationId,
- sub->address.objectId, "parent", true);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DropInherit:
-
- /*
- * Syntax: NO INHERIT %{parent}D
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "NO INHERIT %{parent}D",
- "type", jbvString, "drop inherit");
- new_jsonb_for_qualname_id(state, RelationRelationId,
- sub->address.objectId, "parent", true);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_AddOf:
-
- /*
- * Syntax: OF %{type_of}T
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "OF %{type_of}T",
- "type", jbvString, "add of");
- new_jsonb_for_type(state, "type_of", sub->address.objectId, -1);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DropOf:
-
- /*
- * Syntax: NOT OF
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "NOT OF",
- "type", jbvString, "not of");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_ReplicaIdentity:
-
- /*
- * Syntax: REPLICA IDENTITY %{ident}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString,
- "REPLICA IDENTITY %{ident}s",
- "type", jbvString, "replica identity");
- switch (((ReplicaIdentityStmt *) subcmd->def)->identity_type)
- {
- case REPLICA_IDENTITY_DEFAULT:
- new_jsonb_VA(state, 1, "ident", jbvString, "DEFAULT");
- break;
- case REPLICA_IDENTITY_FULL:
- new_jsonb_VA(state, 1, "ident", jbvString, "FULL");
- break;
- case REPLICA_IDENTITY_NOTHING:
- new_jsonb_VA(state, 1, "ident", jbvString, "NOTHING");
- break;
- case REPLICA_IDENTITY_INDEX:
- insert_jsonb_key(state, "ident");
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "USING INDEX %{index}I",
- "index", jbvString,
- ((ReplicaIdentityStmt *) subcmd->def)->name);
- break;
- }
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_EnableRowSecurity:
-
- /*
- * Syntax: ENABLE ROW LEVEL SECURITY
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString,
- "ENABLE ROW LEVEL SECURITY",
- "type", jbvString, "enable row security");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_DisableRowSecurity:
-
- /*
- * Syntax: DISABLE ROW LEVEL SECURITY
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString,
- "DISABLE ROW LEVEL SECURITY",
- "type", jbvString, "disable row security");
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
-
- case AT_AttachPartition:
- {
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: ATTACH PARTITION %{partition_identity}D
- * %{partition_bound}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- appendStringInfoString(&fmtSub, "ATTACH PARTITION"
- " %{partition_identity}D");
-
- new_jsonb_VA(state, 1, "type", jbvString,
- "attach partition");
- new_jsonb_for_qualname_id(state, RelationRelationId,
- sub->address.objectId,
- "partition_identity", true);
-
- if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
- {
- appendStringInfoString(&fmtSub, " %{partition_bound}s");
- new_jsonb_VA(state, 1,
- "partition_bound", jbvString,
- RelationGetPartitionBound(sub->address.objectId));
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- break;
- }
- case AT_DetachPartition:
- {
- PartitionCmd *cmd;
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- Assert(IsA(subcmd->def, PartitionCmd));
- cmd = (PartitionCmd *) subcmd->def;
-
- /*
- * Syntax: DETACH PARTITION %{partition_identity}D
- * %{concurrent}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- appendStringInfoString(&fmtSub, "DETACH PARTITION"
- " %{partition_identity}D");
-
- new_jsonb_VA(state, 1, "type", jbvString, "detach partition");
- new_jsonb_for_qualname_id(state, RelationRelationId,
- sub->address.objectId,
- "partition_identity", true);
- if (cmd->concurrent)
- {
- appendStringInfoString(&fmtSub, " %{concurrent}s");
- new_jsonb_VA(state, 1,
- "concurrent", jbvString, "CONCURRENTLY");
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
- }
- case AT_DetachPartitionFinalize:
-
- /*
- * Syntax: DETACH PARTITION %{partition_identity}D FINALIZE
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 2,
- "fmt", jbvString, "DETACH PARTITION"
- " %{partition_identity}D FINALIZE",
- "type", jbvString, "detach partition finalize");
-
- new_jsonb_for_qualname_id(state, RelationRelationId,
- sub->address.objectId,
- "partition_identity", true);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
- case AT_AddIdentity:
- {
- AttrNumber attnum;
- Oid seq_relid;
- ColumnDef *coldef = (ColumnDef *) subcmd->def;
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: ALTER COLUMN %{column}I %{definition}s where
- * definition : ADD %{identity_column}s where
- * identity_column: %{identity_type}s ( %{seq_definition:
- * }s )
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- appendStringInfoString(&fmtSub, "ALTER COLUMN %{column}I");
- new_jsonb_VA(state, 2,
- "type", jbvString, "add identity",
- "column", jbvString, subcmd->name);
-
- attnum = get_attnum(RelationGetRelid(rel), subcmd->name);
- seq_relid = getIdentitySequence(RelationGetRelid(rel),
- attnum, true);
-
- if (OidIsValid(seq_relid))
- {
-
- appendStringInfoString(&fmtSub, " %{definition}s");
- insert_jsonb_key(state, "definition");
-
- /* insert definition's value now */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- new_jsonb_VA(state, 1,
- "fmt", jbvString, "ADD %{identity_column}s");
-
- /* insert identity_column */
- deparse_ColumnIdentity_toJsonb(state, "identity_column",
- seq_relid,
- coldef->identity, false);
-
- /* mark definition's value end */
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
-
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- }
- break;
- case AT_SetIdentity:
- {
- DefElem *defel;
- char identity = 0;
- AttrNumber attnum;
- Oid seq_relid;
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: ALTER COLUMN %{column}I %{definition}s where
- * definition : %{identity_type}s ( %{seq_definition: }s )
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
-
- appendStringInfoString(&fmtSub, "ALTER COLUMN %{column}I");
- new_jsonb_VA(state, 2,
- "type", jbvString, "set identity",
- "column", jbvString, subcmd->name);
-
- if (subcmd->def)
- {
- List *def = (List *) subcmd->def;
-
- Assert(IsA(subcmd->def, List));
-
- defel = linitial_node(DefElem, def);
- identity = defGetInt32(defel);
- }
-
- attnum = get_attnum(RelationGetRelid(rel), subcmd->name);
- seq_relid = getIdentitySequence(RelationGetRelid(rel),
- attnum, true);
-
- if (OidIsValid(seq_relid))
- {
- appendStringInfoString(&fmtSub, " %{definition}s");
- deparse_ColumnIdentity_toJsonb(state, "definition",
- seq_relid, identity,
- true);
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
-
- pfree(fmtSub.data);
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- break;
- }
- case AT_DropIdentity:
- {
- StringInfoData fmtSub;
-
- initStringInfo(&fmtSub);
-
- /*
- * Syntax: ALTER COLUMN %{column}I DROP IDENTITY
- * %{if_exists}s
- */
- pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
- appendStringInfoString(&fmtSub, "ALTER COLUMN"
- " %{column}I DROP IDENTITY");
- new_jsonb_VA(state, 2,
- "type", jbvString, "drop identity",
- "column", jbvString, subcmd->name);
-
- if (subcmd->missing_ok)
- {
- appendStringInfoString(&fmtSub, " %{if_exists}s");
- new_jsonb_VA(state, 1,
- "if_exists", jbvString, "IF EXISTS");
- }
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
- pfree(fmtSub.data);
-
- pushJsonbValue(&state, WJB_END_OBJECT, NULL);
- break;
- }
- default:
- elog(WARNING, "unsupported alter table subtype %d",
- subcmd->subtype);
- break;
- }
- }
-
- table_close(rel, AccessShareLock);
-
- /* if subcmds array is not even created or has 0 elements, return NULL */
- if (!subCmdArray ||
- ((state->contVal.type == jbvArray) &&
- (state->contVal.val.array.nElems == 0)))
- {
- pfree(fmtStr.data);
- return NULL;
- }
-
- /* Mark the end of subcmds array */
- pushJsonbValue(&state, WJB_END_ARRAY, NULL);
-
- /* We have full fmt by now, so add jsonb element for that */
- new_jsonb_VA(state, 1, "fmt", jbvString, fmtStr.data);
-
- pfree(fmtStr.data);
-
- /* Mark the end of ROOT object */
- value = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
-
- return JsonbValueToJsonb(value);
-}
-
/*
* Deparse a CreateSeqStmt.
*
@@ -3641,7 +2054,7 @@ deparse_simple_command(CollectedCommand *cmd)
return deparse_CreateSeqStmt(objectId, parsetree);
case T_CreateStmt:
- return deparse_CreateStmt(objectId, parsetree);
+ return deparse_create_table(objectId, parsetree);
case T_RenameStmt:
return deparse_RenameStmt(cmd->d.simple.address, parsetree);
diff --git a/src/backend/nodes/Makefile b/src/backend/nodes/Makefile
index 0a95e683d0..a26607b9b1 100644
--- a/src/backend/nodes/Makefile
+++ b/src/backend/nodes/Makefile
@@ -17,6 +17,7 @@ override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
OBJS = \
bitmapset.o \
copyfuncs.o \
+ ddldeparsefuncs.o \
equalfuncs.o \
extensible.o \
list.o \
diff --git a/src/backend/nodes/ddldeparsefuncs.c b/src/backend/nodes/ddldeparsefuncs.c
new file mode 100644
index 0000000000..9cd42fd7e3
--- /dev/null
+++ b/src/backend/nodes/ddldeparsefuncs.c
@@ -0,0 +1,1636 @@
+/*-------------------------------------------------------------------------
+ *
+ * ddldeparsefuncs.c
+ * DDL deparsing.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/nodes/ddldeparsefuncs.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/amapi.h"
+#include "access/relation.h"
+#include "access/table.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_constraint.h"
+#include "catalog/pg_depend.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "commands/defrem.h"
+#include "commands/sequence.h"
+#include "commands/tablespace.h"
+#include "commands/tablecmds.h"
+#include "funcapi.h"
+#include "optimizer/optimizer.h"
+#include "rewrite/rewriteHandler.h"
+#include "tcop/ddldeparse.h"
+#include "tcop/utility.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/guc.h"
+#include "utils/jsonb.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/ruleutils.h"
+#include "utils/syscache.h"
+
+/* Estimated length of the generated jsonb string */
+#define JSONB_ESTIMATED_LEN 128
+
+extern bool verbose;
+
+/*
+ * Deparse a CreateStmt (CREATE TABLE).
+ *
+ * Given a table OID and the parse tree that created it, return JsonbValue
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D [OF
+ * %{of_type}T | PARTITION OF %{parent_identity}D] %{table_elements}s
+ * %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s
+ * %{tablespace}s
+ */
+Jsonb *
+deparse_create_table(Oid objectId, Node *parsetree)
+{
+ CreateStmt *node = (CreateStmt *) parsetree;
+ Relation relation = relation_open(objectId, AccessShareLock);
+ Oid nspid = relation->rd_rel->relnamespace;
+ char *relname = RelationGetRelationName(relation);
+ List *dpcontext;
+ char *perstr;
+ StringInfoData fmtStr;
+ JsonbParseState *state = NULL;
+ JsonbValue *value;
+
+ initStringInfo(&fmtStr);
+
+ /* mark the begin of ROOT object and start adding elements to it. */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ appendStringInfoString(&fmtStr, "CREATE");
+
+ /* PERSISTENCE */
+ perstr = get_persistence_str(relation->rd_rel->relpersistence);
+ if (perstr)
+ {
+ appendStringInfoString(&fmtStr, " %{persistence}s");
+ new_jsonb_VA(state, 1,
+ "persistence", jbvString, perstr);
+ }
+
+ appendStringInfoString(&fmtStr, " TABLE");
+
+ /* IF NOT EXISTS */
+ if (node->if_not_exists)
+ {
+ appendStringInfoString(&fmtStr, " %{if_not_exists}s");
+ new_jsonb_VA(state, 1,
+ "if_not_exists", jbvString, "IF NOT EXISTS");
+ }
+
+ /* IDENTITY */
+ appendStringInfoString(&fmtStr, " %{identity}D");
+ insert_identity_object(state, nspid, relname);
+
+ dpcontext = deparse_context_for(RelationGetRelationName(relation),
+ objectId);
+
+ /*
+ * TABLE-ELEMENTS array creation
+ *
+ * Typed tables and partitions use a slightly different format string: we
+ * must not put table_elements with parents directly in the fmt string,
+ * because if there are no options the parentheses must not be emitted;
+ * and also, typed tables do not allow for inheritance.
+ */
+ if (node->ofTypename || node->partbound)
+ {
+ /* Insert the "of type" or "partition of" clause whichever present */
+ if (node->ofTypename)
+ {
+ appendStringInfoString(&fmtStr, " OF %{of_type}T");
+ new_jsonb_for_type(state, "of_type",
+ relation->rd_rel->reloftype, -1);
+ }
+ else
+ {
+ List *parents;
+ Oid objid;
+
+ appendStringInfoString(&fmtStr, " PARTITION OF %{parent_identity}D");
+ parents = deparse_InhRels_ToJsonb(objectId);
+ objid = linitial_oid(parents);
+ Assert(list_length(parents) == 1);
+ new_jsonb_for_qualname_id(state, RelationRelationId,
+ objid, "parent_identity", true);
+ }
+
+ /*
+ * We can't put table elements directly in the fmt string as an array
+ * surrounded by parentheses here, because an empty clause would cause
+ * a syntax error. Therefore, we first check the presence and then add
+ * the elements.
+ */
+ add_table_elems_if_any(state, &fmtStr, relation,
+ node->tableElts, dpcontext, objectId,
+ true, /* typed table */
+ false); /* not composite */
+ }
+ else
+ {
+ List *inhrelations;
+ bool telems_present = false;
+
+ /*
+ * There is no need to process LIKE clauses separately; they have
+ * already been transformed into columns and constraints.
+ */
+
+ /* Check if table elements are present, if so, add them. */
+ telems_present = add_table_elems_if_any(state, &fmtStr, relation,
+ node->tableElts, dpcontext, objectId,
+ false, /* not typed table */
+ false); /* not composite */
+
+ /*
+ * If no table elements added, then add empty "()" needed for
+ * 'inherit' create table syntax. Example: CREATE TABLE t1 () INHERITS
+ * (t0);
+ */
+ if (!telems_present)
+ appendStringInfoString(&fmtStr, " ()");
+
+ /*
+ * Add inheritance specification. We cannot simply scan the list of
+ * parents from the parser node, because that may lack the actual
+ * qualified names of the parent relations. Rather than trying to
+ * re-resolve them from the information in the parse node, it seems
+ * more accurate and convenient to grab it from pg_inherits.
+ */
+ if (node->inhRelations != NIL)
+ {
+ appendStringInfoString(&fmtStr, " %{inherits}s");
+ insert_jsonb_key(state, "inherits");
+
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ new_jsonb_VA(state, 1, "fmt", jbvString, "INHERITS (%{parents:, }D)");
+ inhrelations = deparse_InhRels_ToJsonb(objectId);
+
+ new_jsonbArray_for_qualname_id(state, "parents", inhrelations);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+ }
+
+ /* FOR VALUES clause */
+ if (node->partbound)
+ {
+ appendStringInfoString(&fmtStr, " %{partition_bound}s");
+
+ /*
+ * Get pg_class.relpartbound. We cannot use partbound in the parsetree
+ * directly as it's the original partbound expression which haven't
+ * been transformed.
+ */
+ new_jsonb_VA(state, 1,
+ "partition_bound", jbvString,
+ RelationGetPartitionBound(objectId));
+ }
+
+ /* PARTITION BY clause */
+ if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ appendStringInfoString(&fmtStr, " %{partition_by}s");
+ insert_jsonb_key(state, "partition_by");
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "PARTITION BY %{definition}s",
+ "definition", jbvString,
+ pg_get_partkeydef_string(objectId));
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+
+ /* USING clause */
+ if (node->accessMethod)
+ {
+ appendStringInfoString(&fmtStr, " %{access_method}s");
+ insert_jsonb_key(state, "access_method");
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "USING %{access_method}I",
+ "access_method", jbvString, node->accessMethod);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+
+ /* WITH clause */
+ if (node->options)
+ {
+ appendStringInfoString(&fmtStr, " %{with_clause}s");
+ insert_jsonb_key(state, "with_clause");
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 1,
+ "fmt", jbvString, "WITH (%{with:, }s)");
+
+ deparse_withObj_ToJsonb(state, node);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ }
+
+ /* TABLESPACE */
+ if (node->tablespacename)
+ {
+ appendStringInfoString(&fmtStr, " %{tablespace}s");
+ insert_jsonb_key(state, "tablespace");
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "TABLESPACE %{tablespace}I",
+ "tablespace", jbvString, node->tablespacename);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+
+ relation_close(relation, AccessShareLock);
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtStr.data);
+
+ pfree(fmtStr.data);
+
+ /* Mark the end of ROOT object */
+ value = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ return JsonbValueToJsonb(value);
+}
+
+/*
+ * Deparse a DropStmt (DROP TABLE).
+ *
+ * Given an object identity and the parse tree that created it, return
+ * jsonb string representing the drop command.
+ *
+ * Verbose syntax
+ * DROP %{objtype}s %{concurrently}s %{if_exists}s %{objidentity}s %{cascade}s
+ */
+char *
+deparse_drop_table(const char *objidentity, const char *objecttype,
+ Node *parsetree)
+{
+ DropStmt *node = (DropStmt *) parsetree;
+ StringInfoData fmtStr;
+ JsonbValue *jsonbval;
+ Jsonb *jsonb;
+ StringInfoData str;
+ JsonbParseState *state = NULL;
+
+ initStringInfo(&str);
+ initStringInfo(&fmtStr);
+
+ /* mark the begin of ROOT object and start adding elements to it. */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ /* Start constructing fmt string */
+ appendStringInfoString(&fmtStr, "DROP %{objtype}s");
+
+ /* OBJTYPE */
+ new_jsonb_VA(state, 1, "objtype", jbvString, objecttype);
+
+ /* CONCURRENTLY */
+ if (node->concurrent)
+ {
+ appendStringInfoString(&fmtStr, " %{concurrently}s");
+ new_jsonb_VA(state, 1,
+ "concurrently", jbvString, "CONCURRENTLY");
+ }
+
+ /* IF EXISTS */
+ if (node->missing_ok)
+ {
+ appendStringInfoString(&fmtStr, " %{if_exists}s");
+ new_jsonb_VA(state, 1, "if_exists", jbvString, "IF EXISTS");
+ }
+
+ /* IDENTITY */
+ appendStringInfoString(&fmtStr, " %{objidentity}s");
+ new_jsonb_VA(state, 1, "objidentity", jbvString, objidentity);
+
+ /* CASCADE */
+ if (node->behavior == DROP_CASCADE)
+ {
+ appendStringInfoString(&fmtStr, " %{cascade}s");
+ new_jsonb_VA(state, 1, "cascade", jbvString, "CASCADE");
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtStr.data);
+ pfree(fmtStr.data);
+
+ jsonbval = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ jsonb = JsonbValueToJsonb(jsonbval);
+ return JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
+}
+
+/*
+ * Deparse all the collected subcommands and return jsonb string representing
+ * the alter command.
+ *
+ * Verbose syntax
+ * ALTER %{objtype}s %{only}s %{identity}D %{subcmds:, }s
+ */
+Jsonb *
+deparse_AlterTableStmt(CollectedCommand *cmd)
+{
+ List *dpcontext;
+ Relation rel;
+ ListCell *cell;
+ const char *reltype;
+ Oid relId = cmd->d.alterTable.objectId;
+ AlterTableStmt *stmt = NULL;
+ StringInfoData fmtStr;
+ JsonbParseState *state = NULL;
+ bool subCmdArray = false;
+ JsonbValue *value;
+
+ Assert(cmd->type == SCT_AlterTable);
+ stmt = (AlterTableStmt *) cmd->parsetree;
+
+ Assert(IsA(stmt, AlterTableStmt) || IsA(stmt, AlterTableMoveAllStmt));
+
+ initStringInfo(&fmtStr);
+
+ /*
+ * ALTER TABLE subcommands generated for TableLikeClause is processed in
+ * the top level CREATE TABLE command; return empty here.
+ */
+ if (IsA(stmt, AlterTableStmt) && stmt->table_like)
+ return NULL;
+
+ rel = relation_open(relId, AccessShareLock);
+
+ switch (rel->rd_rel->relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
+ reltype = "TABLE";
+ break;
+ case RELKIND_INDEX:
+ case RELKIND_PARTITIONED_INDEX:
+ case RELKIND_VIEW:
+ case RELKIND_COMPOSITE_TYPE:
+ case RELKIND_FOREIGN_TABLE:
+ case RELKIND_MATVIEW:
+ /* unsupported relkind */
+ table_close(rel, AccessShareLock);
+ return NULL;
+
+ default:
+ elog(ERROR, "unexpected relkind %d", rel->rd_rel->relkind);
+ }
+
+
+ dpcontext = deparse_context_for(RelationGetRelationName(rel), relId);
+
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ /* Start constructing fmt string */
+ appendStringInfoString(&fmtStr, "ALTER %{objtype}s");
+
+ new_jsonb_VA(state, 1, "objtype", jbvString, reltype);
+
+ if (!stmt->relation->inh)
+ {
+ appendStringInfoString(&fmtStr, " %{only}s");
+ new_jsonb_VA(state, 1, "only", jbvString, "ONLY");
+ }
+
+ appendStringInfoString(&fmtStr, " %{identity}D");
+ insert_identity_object(state, rel->rd_rel->relnamespace,
+ RelationGetRelationName(rel));
+
+ foreach(cell, cmd->d.alterTable.subcmds)
+ {
+ CollectedATSubcmd *sub = (CollectedATSubcmd *) lfirst(cell);
+ AlterTableCmd *subcmd = (AlterTableCmd *) sub->parsetree;
+
+ Assert(IsA(subcmd, AlterTableCmd));
+
+ /*
+ * Skip deparse of the subcommand if the objectId doesn't match the
+ * target relation ID. It can happen for inherited tables when
+ * subcommands for inherited tables and the parent table are both
+ * collected in the ALTER TABLE command for the parent table.
+ */
+ if (subcmd->subtype != AT_AttachPartition &&
+ sub->address.objectId != relId &&
+ has_superclass(sub->address.objectId))
+ continue;
+
+ /* Mark the begin of subcmds array */
+ if (!subCmdArray)
+ {
+ appendStringInfoString(&fmtStr, " %{subcmds:, }s");
+ insert_jsonb_key(state, "subcmds");
+ pushJsonbValue(&state, WJB_BEGIN_ARRAY, NULL);
+ subCmdArray = true;
+ }
+
+ switch (subcmd->subtype)
+ {
+ case AT_AddColumn:
+ {
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /* XXX need to set the "recurse" bit somewhere? */
+ Assert(IsA(subcmd->def, ColumnDef));
+
+ /*
+ * Syntax: ADD COLUMN %{if_not_exists}s %{definition}s"
+ * where definition: "%{name}I %{coltype}T STORAGE
+ * %{colstorage}s %{compression}s %{collation}s
+ * %{not_null}s %{default}s %{identity_column}s
+ * %{generated_column}s"
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ appendStringInfoString(&fmtSub, "ADD COLUMN");
+ new_jsonb_VA(state, 1, "type", jbvString, "add column");
+
+ if (subcmd->missing_ok)
+ {
+ appendStringInfoString(&fmtSub, " %{if_not_exists}s");
+ new_jsonb_VA(state, 1,
+ "if_not_exists", jbvString, "IF NOT EXISTS");
+ }
+
+ /* Push definition key-value pair */
+ appendStringInfoString(&fmtSub, " %{definition}s");
+ insert_jsonb_key(state, "definition");
+
+ deparse_ColumnDef_toJsonb(state, rel, dpcontext,
+ false, (ColumnDef *) subcmd->def,
+ true);
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+ }
+
+ case AT_AddIndexConstraint:
+ {
+ IndexStmt *istmt;
+ Relation idx;
+ Oid conOid = sub->address.objectId;
+
+ Assert(IsA(subcmd->def, IndexStmt));
+ istmt = (IndexStmt *) subcmd->def;
+
+ Assert(istmt->isconstraint && istmt->unique);
+
+ idx = relation_open(istmt->indexOid, AccessShareLock);
+
+ /*
+ * Syntax: ADD CONSTRAINT %{name}I %{constraint_type}s
+ * USING INDEX %index_name}I %{deferrable}s
+ * %{init_deferred}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ new_jsonb_VA(state, 7,
+ "fmt", jbvString,
+ "ADD CONSTRAINT %{name}I %{constraint_type}s"
+ " USING INDEX %{index_name}I %{deferrable}s"
+ " %{init_deferred}s",
+ "type", jbvString, "add constraint using index",
+ "name", jbvString, get_constraint_name(conOid),
+ "constraint_type", jbvString,
+ istmt->primary ? "PRIMARY KEY" : "UNIQUE",
+ "index_name", jbvString,
+ RelationGetRelationName(idx),
+ "deferrable", jbvString,
+ istmt->deferrable ? "DEFERRABLE" :
+ "NOT DEFERRABLE",
+ "init_deferred", jbvString,
+ istmt->initdeferred ? "INITIALLY DEFERRED" :
+ "INITIALLY IMMEDIATE");
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ relation_close(idx, AccessShareLock);
+ break;
+ }
+ case AT_ReAddIndex:
+ case AT_ReAddConstraint:
+ case AT_ReAddDomainConstraint:
+ case AT_ReAddComment:
+ case AT_ReplaceRelOptions:
+ case AT_CheckNotNull:
+ case AT_ReAddStatistics:
+ /* Subtypes used for internal operations; nothing to do here */
+ break;
+
+ case AT_ColumnDefault:
+ if (subcmd->def == NULL)
+ {
+ /*
+ * Syntax: ALTER COLUMN %{column}I DROP DEFAULT
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I DROP DEFAULT",
+ "type", jbvString, "drop default",
+ "column", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+ else
+ {
+ List *dpcontext_rel;
+ HeapTuple attrtup;
+ AttrNumber attno;
+
+ dpcontext_rel = deparse_context_for(
+ RelationGetRelationName(rel),
+ RelationGetRelid(rel));
+ attrtup = SearchSysCacheAttName(RelationGetRelid(rel),
+ subcmd->name);
+ attno = ((Form_pg_attribute) GETSTRUCT(attrtup))->attnum;
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I SET DEFAULT
+ * %{definition}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ new_jsonb_VA(state, 4,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I SET DEFAULT"
+ " %{definition}s",
+ "type", jbvString, "set default",
+ "column", jbvString, subcmd->name,
+ "definition", jbvString,
+ RelationGetColumnDefault(rel, attno,
+ dpcontext_rel));
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ ReleaseSysCache(attrtup);
+ }
+
+ break;
+
+ case AT_DropNotNull:
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I DROP NOT NULL
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I DROP NOT NULL",
+ "type", jbvString, "drop not null",
+ "column", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_ForceRowSecurity:
+
+ /*
+ * Syntax: FORCE ROW LEVEL SECURITY
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 1, "fmt", jbvString,
+ "FORCE ROW LEVEL SECURITY");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_NoForceRowSecurity:
+
+ /*
+ * Syntax: NO FORCE ROW LEVEL SECURITY
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 1, "fmt", jbvString,
+ "NO FORCE ROW LEVEL SECURITY");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetNotNull:
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I SET NOT NULL
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I SET NOT NULL",
+ "type", jbvString, "set not null",
+ "column", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DropExpression:
+ {
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I DROP EXPRESSION
+ * %{if_exists}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ appendStringInfoString(&fmtSub, "ALTER COLUMN"
+ " %{column}I DROP EXPRESSION");
+ new_jsonb_VA(state, 2,
+ "type", jbvString, "drop expression",
+ "column", jbvString, subcmd->name);
+
+ if (subcmd->missing_ok)
+ {
+ appendStringInfoString(&fmtSub, " %{if_exists}s");
+ new_jsonb_VA(state, 1,
+ "if_exists", jbvString, "IF EXISTS");
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+ }
+
+ case AT_SetStatistics:
+ Assert(IsA(subcmd->def, Integer));
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I SET STATISTICS
+ * %{statistics}n
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 4,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I SET STATISTICS"
+ " %{statistics}n",
+ "type", jbvString, "set statistics",
+ "column", jbvString, subcmd->name,
+ "statistics", jbvNumeric,
+ intVal((Integer *) subcmd->def));
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetOptions:
+ case AT_ResetOptions:
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I RESET|SET (%{options:, }s)
+ */
+ deparse_ColumnSetOptions_ToJsonb(state, subcmd);
+ break;
+
+ case AT_SetStorage:
+ Assert(IsA(subcmd->def, String));
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I SET STORAGE %{storage}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 4,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I SET STORAGE"
+ " %{storage}s",
+ "type", jbvString, "set storage",
+ "column", jbvString, subcmd->name,
+ "storage", jbvString,
+ strVal((String *) subcmd->def));
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetCompression:
+ Assert(IsA(subcmd->def, String));
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I SET COMPRESSION
+ * %{compression_method}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 4,
+ "fmt", jbvString,
+ "ALTER COLUMN %{column}I SET COMPRESSION"
+ " %{compression_method}s",
+ "type", jbvString, "set compression",
+ "column", jbvString, subcmd->name,
+ "compression_method", jbvString,
+ strVal((String *) subcmd->def));
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DropColumn:
+ {
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: DROP COLUMN %{if_exists}s %{column}I
+ * %{cascade}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ appendStringInfoString(&fmtSub, "DROP COLUMN");
+ new_jsonb_VA(state, 1, "type", jbvString, "drop column");
+
+ if (subcmd->missing_ok)
+ {
+ appendStringInfoString(&fmtSub, " %{if_exists}s");
+ new_jsonb_VA(state, 1,
+ "if_exists", jbvString, "IF EXISTS");
+ }
+
+ appendStringInfoString(&fmtSub, " %{column}I");
+ new_jsonb_VA(state, 1, "column", jbvString, subcmd->name);
+
+ if (subcmd->behavior == DROP_CASCADE)
+ {
+ appendStringInfoString(&fmtSub, " %{cascade}s");
+ new_jsonb_VA(state, 1,
+ "cascade", jbvString, "CASCADE");
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ break;
+ }
+ case AT_AddIndex:
+ {
+ Oid idxOid = sub->address.objectId;
+ IndexStmt *istmt PG_USED_FOR_ASSERTS_ONLY =
+ (IndexStmt *) subcmd->def;
+ Relation idx;
+ const char *idxname;
+ Oid constrOid;
+
+ Assert(IsA(subcmd->def, IndexStmt));
+ Assert(istmt->isconstraint);
+
+ idx = relation_open(idxOid, AccessShareLock);
+ idxname = RelationGetRelationName(idx);
+
+ constrOid = get_relation_constraint_oid(
+ cmd->d.alterTable.objectId,
+ idxname, false);
+
+ /*
+ * Syntax: ADD CONSTRAINT %{name}I %{definition}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ new_jsonb_VA(state, 4,
+ "fmt", jbvString,
+ "ADD CONSTRAINT %{name}I %{definition}s",
+ "type", jbvString, "add constraint",
+ "name", jbvString, idxname,
+ "definition", jbvString,
+ pg_get_constraintdef_string(constrOid));
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ relation_close(idx, AccessShareLock);
+ }
+ break;
+ case AT_AddConstraint:
+ {
+ /* XXX need to set the "recurse" bit somewhere? */
+ Oid constrOid = sub->address.objectId;
+
+ /* Skip adding constraint for inherits table sub command */
+ if (!OidIsValid(constrOid))
+ continue;
+
+ Assert(IsA(subcmd->def, Constraint));
+
+ /*
+ * Syntax: ADD CONSTRAINT %{name}I %{definition}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 4,
+ "fmt", jbvString,
+ "ADD CONSTRAINT %{name}I %{definition}s",
+ "type", jbvString, "add constraint",
+ "name", jbvString, get_constraint_name(constrOid),
+ "definition", jbvString,
+ pg_get_constraintdef_string(constrOid));
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ break;
+ }
+
+ case AT_AlterConstraint:
+ {
+ Oid conOid = sub->address.objectId;
+ Constraint *c = (Constraint *) subcmd->def;
+
+ /* If no constraint was altered, silently skip it */
+ if (!OidIsValid(conOid))
+ break;
+
+ Assert(IsA(c, Constraint));
+
+ /*
+ * Syntax: ALTER CONSTRAINT %{name}I %{deferrable}s
+ * %{init_deferred}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 5,
+ "fmt", jbvString,
+ "ALTER CONSTRAINT %{name}I %{deferrable}s"
+ " %{init_deferred}s",
+ "type", jbvString, "alter constraint",
+ "name", jbvString, get_constraint_name(conOid),
+ "deferrable", jbvString,
+ c->deferrable ? "DEFERRABLE" : "NOT DEFERRABLE",
+ "init_deferred", jbvString,
+ c->initdeferred ? "INITIALLY DEFERRED" :
+ "INITIALLY IMMEDIATE");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+ break;
+
+ case AT_ValidateConstraint:
+
+ /*
+ * Syntax: VALIDATE CONSTRAINT %{constraint}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "VALIDATE CONSTRAINT %{constraint}I",
+ "type", jbvString, "validate constraint",
+ "constraint", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DropConstraint:
+ {
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: DROP CONSTRAINT %{if_exists}s %{constraint}I
+ * %{cascade}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ appendStringInfoString(&fmtSub, "DROP CONSTRAINT");
+ new_jsonb_VA(state, 1, "type", jbvString, "drop constraint");
+
+ if (subcmd->missing_ok)
+ {
+ appendStringInfoString(&fmtSub, " %{if_exists}s");
+ new_jsonb_VA(state, 1,
+ "if_exists", jbvString, "IF EXISTS");
+ }
+
+ appendStringInfoString(&fmtSub, " %{constraint}I");
+ new_jsonb_VA(state, 1,
+ "constraint", jbvString, subcmd->name);
+
+ if (subcmd->behavior == DROP_CASCADE)
+ {
+ appendStringInfoString(&fmtSub, " %{cascade}s");
+ new_jsonb_VA(state, 1, "cascade", jbvString, "CASCADE");
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+ break;
+
+ case AT_AlterColumnType:
+ {
+ TupleDesc tupdesc = RelationGetDescr(rel);
+ Form_pg_attribute att;
+ ColumnDef *def;
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ att = &(tupdesc->attrs[sub->address.objectSubId - 1]);
+ def = (ColumnDef *) subcmd->def;
+ Assert(IsA(def, ColumnDef));
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I SET DATA TYPE
+ * %{datatype}T %{collation}s %{using}s where using: USING
+ * %{expression}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ appendStringInfoString(&fmtSub, "ALTER COLUMN %{column}I"
+ " SET DATA TYPE %{datatype}T");
+ new_jsonb_VA(state, 2,
+ "type", jbvString, "alter column type",
+ "column", jbvString, subcmd->name);
+
+ new_jsonb_for_type(state, "datatype",
+ att->atttypid, att->atttypmod);
+
+ /* Add a COLLATE clause, if needed */
+ if (OidIsValid(att->attcollation))
+ {
+ appendStringInfoString(&fmtSub, " %{collation}s");
+ insert_collate_object(state, "collation",
+ "COLLATE %{name}D",
+ CollationRelationId,
+ att->attcollation, "name");
+ }
+
+ /*
+ * If there's a USING clause, transformAlterTableStmt ran
+ * it through transformExpr and stored the resulting node
+ * in cooked_default, which we can use here.
+ */
+ if (def->raw_default)
+ {
+ Datum deparsed;
+ char *defexpr;
+ List *exprs = NIL;
+
+ exprs = lappend(exprs, def->cooked_default);
+ defexpr = nodeToString(def->cooked_default);
+ deparsed = DirectFunctionCall2(pg_get_expr,
+ CStringGetTextDatum(defexpr),
+ RelationGetRelid(rel));
+ appendStringInfoString(&fmtSub, " %{using}s");
+ insert_jsonb_key(state, "using");
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "USING %{expression}s",
+ "expression", jbvString,
+ TextDatumGetCString(deparsed));
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+
+ pfree(fmtSub.data);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+ break;
+
+ case AT_ChangeOwner:
+
+ /*
+ * Syntax: OWNER TO %{owner}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "OWNER TO %{owner}I",
+ "type", jbvString, "change owner",
+ "owner", jbvString,
+ get_rolespec_name(subcmd->newowner));
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_ClusterOn:
+
+ /*
+ * Syntax: CLUSTER ON %{index}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "CLUSTER ON %{index}I",
+ "type", jbvString, "cluster on",
+ "index", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+
+ case AT_DropCluster:
+
+ /*
+ * Syntax: SET WITHOUT CLUSTER
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "SET WITHOUT CLUSTER",
+ "type", jbvString, "set without cluster");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetLogged:
+
+ /*
+ * Syntax: SET LOGGED
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "SET LOGGED",
+ "type", jbvString, "set logged");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetUnLogged:
+
+ /*
+ * Syntax: SET UNLOGGED
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "SET UNLOGGED",
+ "type", jbvString, "set unlogged");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DropOids:
+
+ /*
+ * Syntax: SET WITHOUT OIDS
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "SET WITHOUT OIDS",
+ "type", jbvString, "set without oids");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetAccessMethod:
+
+ /*
+ * Syntax: SET ACCESS METHOD %{access_method}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "SET ACCESS METHOD %{access_method}I",
+ "type", jbvString, "set access method",
+ "access_method", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetTableSpace:
+
+ /*
+ * Syntax: SET TABLESPACE %{tablespace}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "SET TABLESPACE %{tablespace}I",
+ "type", jbvString, "set tablespace",
+ "tablespace", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_SetRelOptions:
+ case AT_ResetRelOptions:
+
+ /*
+ * Syntax: SET|RESET (%{options:, }s)
+ */
+ deparse_RelSetOptions_toJsonb(state, subcmd);
+ break;
+
+ case AT_EnableTrig:
+
+ /*
+ * Syntax: ENABLE TRIGGER %{trigger}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "ENABLE TRIGGER %{trigger}I",
+ "type", jbvString, "enable trigger",
+ "trigger", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableAlwaysTrig:
+
+ /*
+ * Syntax: ENABLE ALWAYS TRIGGER %{trigger}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "ENABLE ALWAYS TRIGGER %{trigger}I",
+ "type", jbvString, "enable always trigger",
+ "trigger", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableReplicaTrig:
+
+ /*
+ * Syntax: ENABLE REPLICA TRIGGER %{trigger}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString,
+ "ENABLE REPLICA TRIGGER %{trigger}I",
+ "type", jbvString, "enable replica trigger",
+ "trigger", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DisableTrig:
+
+ /*
+ * Syntax: DISABLE TRIGGER %{trigger}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "DISABLE TRIGGER %{trigger}I",
+ "type", jbvString, "disable trigger",
+ "trigger", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableTrigAll:
+
+ /*
+ * Syntax: ENABLE TRIGGER ALL
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "ENABLE TRIGGER ALL",
+ "type", jbvString, "enable trigger all");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DisableTrigAll:
+
+ /*
+ * Syntax: DISABLE TRIGGER ALL
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "DISABLE TRIGGER ALL",
+ "type", jbvString, "disable trigger all");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableTrigUser:
+
+ /*
+ * Syntax: ENABLE TRIGGER USER
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "ENABLE TRIGGER USER",
+ "type", jbvString, "enable trigger user");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DisableTrigUser:
+
+ /*
+ * Syntax: DISABLE TRIGGER USER
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "DISABLE TRIGGER USER",
+ "type", jbvString, "disable trigger user");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableRule:
+
+ /*
+ * Syntax: ENABLE RULE %{rule}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "ENABLE RULE %{rule}I",
+ "type", jbvString, "enable rule",
+ "rule", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableAlwaysRule:
+
+ /*
+ * Syntax: ENABLE ALWAYS RULE %{rule}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "ENABLE ALWAYS RULE %{rule}I",
+ "type", jbvString, "enable always rule",
+ "rule", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableReplicaRule:
+
+ /*
+ * Syntax: ENABLE REPLICA RULE %{rule}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "ENABLE REPLICA RULE %{rule}I",
+ "type", jbvString, "enable replica rule",
+ "rule", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DisableRule:
+
+ /*
+ * Syntax: DISABLE RULE %{rule}I
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 3,
+ "fmt", jbvString, "DISABLE RULE %{rule}I",
+ "type", jbvString, "disable rule",
+ "rule", jbvString, subcmd->name);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_AddInherit:
+
+ /*
+ * Syntax: INHERIT %{parent}D
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "INHERIT %{parent}D",
+ "type", jbvString, "inherit");
+ new_jsonb_for_qualname_id(state, RelationRelationId,
+ sub->address.objectId, "parent", true);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DropInherit:
+
+ /*
+ * Syntax: NO INHERIT %{parent}D
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "NO INHERIT %{parent}D",
+ "type", jbvString, "drop inherit");
+ new_jsonb_for_qualname_id(state, RelationRelationId,
+ sub->address.objectId, "parent", true);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_AddOf:
+
+ /*
+ * Syntax: OF %{type_of}T
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "OF %{type_of}T",
+ "type", jbvString, "add of");
+ new_jsonb_for_type(state, "type_of", sub->address.objectId, -1);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DropOf:
+
+ /*
+ * Syntax: NOT OF
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "NOT OF",
+ "type", jbvString, "not of");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_ReplicaIdentity:
+
+ /*
+ * Syntax: REPLICA IDENTITY %{ident}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString,
+ "REPLICA IDENTITY %{ident}s",
+ "type", jbvString, "replica identity");
+ switch (((ReplicaIdentityStmt *) subcmd->def)->identity_type)
+ {
+ case REPLICA_IDENTITY_DEFAULT:
+ new_jsonb_VA(state, 1, "ident", jbvString, "DEFAULT");
+ break;
+ case REPLICA_IDENTITY_FULL:
+ new_jsonb_VA(state, 1, "ident", jbvString, "FULL");
+ break;
+ case REPLICA_IDENTITY_NOTHING:
+ new_jsonb_VA(state, 1, "ident", jbvString, "NOTHING");
+ break;
+ case REPLICA_IDENTITY_INDEX:
+ insert_jsonb_key(state, "ident");
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "USING INDEX %{index}I",
+ "index", jbvString,
+ ((ReplicaIdentityStmt *) subcmd->def)->name);
+ break;
+ }
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_EnableRowSecurity:
+
+ /*
+ * Syntax: ENABLE ROW LEVEL SECURITY
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString,
+ "ENABLE ROW LEVEL SECURITY",
+ "type", jbvString, "enable row security");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_DisableRowSecurity:
+
+ /*
+ * Syntax: DISABLE ROW LEVEL SECURITY
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString,
+ "DISABLE ROW LEVEL SECURITY",
+ "type", jbvString, "disable row security");
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+
+ case AT_AttachPartition:
+ {
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: ATTACH PARTITION %{partition_identity}D
+ * %{partition_bound}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ appendStringInfoString(&fmtSub, "ATTACH PARTITION"
+ " %{partition_identity}D");
+
+ new_jsonb_VA(state, 1, "type", jbvString,
+ "attach partition");
+ new_jsonb_for_qualname_id(state, RelationRelationId,
+ sub->address.objectId,
+ "partition_identity", true);
+
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ appendStringInfoString(&fmtSub, " %{partition_bound}s");
+ new_jsonb_VA(state, 1,
+ "partition_bound", jbvString,
+ RelationGetPartitionBound(sub->address.objectId));
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ break;
+ }
+ case AT_DetachPartition:
+ {
+ PartitionCmd *cmd;
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ Assert(IsA(subcmd->def, PartitionCmd));
+ cmd = (PartitionCmd *) subcmd->def;
+
+ /*
+ * Syntax: DETACH PARTITION %{partition_identity}D
+ * %{concurrent}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ appendStringInfoString(&fmtSub, "DETACH PARTITION"
+ " %{partition_identity}D");
+
+ new_jsonb_VA(state, 1, "type", jbvString, "detach partition");
+ new_jsonb_for_qualname_id(state, RelationRelationId,
+ sub->address.objectId,
+ "partition_identity", true);
+ if (cmd->concurrent)
+ {
+ appendStringInfoString(&fmtSub, " %{concurrent}s");
+ new_jsonb_VA(state, 1,
+ "concurrent", jbvString, "CONCURRENTLY");
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+ }
+ case AT_DetachPartitionFinalize:
+
+ /*
+ * Syntax: DETACH PARTITION %{partition_identity}D FINALIZE
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 2,
+ "fmt", jbvString, "DETACH PARTITION"
+ " %{partition_identity}D FINALIZE",
+ "type", jbvString, "detach partition finalize");
+
+ new_jsonb_for_qualname_id(state, RelationRelationId,
+ sub->address.objectId,
+ "partition_identity", true);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+ case AT_AddIdentity:
+ {
+ AttrNumber attnum;
+ Oid seq_relid;
+ ColumnDef *coldef = (ColumnDef *) subcmd->def;
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I %{definition}s where
+ * definition : ADD %{identity_column}s where
+ * identity_column: %{identity_type}s ( %{seq_definition:
+ * }s )
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ appendStringInfoString(&fmtSub, "ALTER COLUMN %{column}I");
+ new_jsonb_VA(state, 2,
+ "type", jbvString, "add identity",
+ "column", jbvString, subcmd->name);
+
+ attnum = get_attnum(RelationGetRelid(rel), subcmd->name);
+ seq_relid = getIdentitySequence(RelationGetRelid(rel),
+ attnum, true);
+
+ if (OidIsValid(seq_relid))
+ {
+
+ appendStringInfoString(&fmtSub, " %{definition}s");
+ insert_jsonb_key(state, "definition");
+
+ /* insert definition's value now */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ new_jsonb_VA(state, 1,
+ "fmt", jbvString, "ADD %{identity_column}s");
+
+ /* insert identity_column */
+ deparse_ColumnIdentity_toJsonb(state, "identity_column",
+ seq_relid,
+ coldef->identity, false);
+
+ /* mark definition's value end */
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ }
+ break;
+ case AT_SetIdentity:
+ {
+ DefElem *defel;
+ char identity = 0;
+ AttrNumber attnum;
+ Oid seq_relid;
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I %{definition}s where
+ * definition : %{identity_type}s ( %{seq_definition: }s )
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+ appendStringInfoString(&fmtSub, "ALTER COLUMN %{column}I");
+ new_jsonb_VA(state, 2,
+ "type", jbvString, "set identity",
+ "column", jbvString, subcmd->name);
+
+ if (subcmd->def)
+ {
+ List *def = (List *) subcmd->def;
+
+ Assert(IsA(subcmd->def, List));
+
+ defel = linitial_node(DefElem, def);
+ identity = defGetInt32(defel);
+ }
+
+ attnum = get_attnum(RelationGetRelid(rel), subcmd->name);
+ seq_relid = getIdentitySequence(RelationGetRelid(rel),
+ attnum, true);
+
+ if (OidIsValid(seq_relid))
+ {
+ appendStringInfoString(&fmtSub, " %{definition}s");
+ deparse_ColumnIdentity_toJsonb(state, "definition",
+ seq_relid, identity,
+ true);
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+
+ pfree(fmtSub.data);
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ break;
+ }
+ case AT_DropIdentity:
+ {
+ StringInfoData fmtSub;
+
+ initStringInfo(&fmtSub);
+
+ /*
+ * Syntax: ALTER COLUMN %{column}I DROP IDENTITY
+ * %{if_exists}s
+ */
+ pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+ appendStringInfoString(&fmtSub, "ALTER COLUMN"
+ " %{column}I DROP IDENTITY");
+ new_jsonb_VA(state, 2,
+ "type", jbvString, "drop identity",
+ "column", jbvString, subcmd->name);
+
+ if (subcmd->missing_ok)
+ {
+ appendStringInfoString(&fmtSub, " %{if_exists}s");
+ new_jsonb_VA(state, 1,
+ "if_exists", jbvString, "IF EXISTS");
+ }
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtSub.data);
+ pfree(fmtSub.data);
+
+ pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+ break;
+ }
+ default:
+ elog(WARNING, "unsupported alter table subtype %d",
+ subcmd->subtype);
+ break;
+ }
+ }
+
+ table_close(rel, AccessShareLock);
+
+ /* if subcmds array is not even created or has 0 elements, return NULL */
+ if (!subCmdArray ||
+ ((state->contVal.type == jbvArray) &&
+ (state->contVal.val.array.nElems == 0)))
+ {
+ pfree(fmtStr.data);
+ return NULL;
+ }
+
+ /* Mark the end of subcmds array */
+ pushJsonbValue(&state, WJB_END_ARRAY, NULL);
+
+ /* We have full fmt by now, so add jsonb element for that */
+ new_jsonb_VA(state, 1, "fmt", jbvString, fmtStr.data);
+
+ pfree(fmtStr.data);
+
+ /* Mark the end of ROOT object */
+ value = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+
+ return JsonbValueToJsonb(value);
+}
\ No newline at end of file
diff --git a/src/backend/nodes/meson.build b/src/backend/nodes/meson.build
index 31467a12d3..a117ade6ed 100644
--- a/src/backend/nodes/meson.build
+++ b/src/backend/nodes/meson.build
@@ -19,6 +19,7 @@ backend_sources += files(
# add that as an include path for the whole backend
nodefunc_sources = files(
'copyfuncs.c',
+ 'ddldeparsefuncs.c',
'equalfuncs.c',
'queryjumblefuncs.c',
'outfuncs.c',
diff --git a/src/include/tcop/ddldeparse.h b/src/include/tcop/ddldeparse.h
index 8b369fd8c5..0304f34c5d 100644
--- a/src/include/tcop/ddldeparse.h
+++ b/src/include/tcop/ddldeparse.h
@@ -13,10 +13,50 @@
#define DDL_DEPARSE_H
#include "tcop/deparse_utility.h"
+#include "utils/jsonb.h"
+extern void new_jsonb_VA(JsonbParseState *state, int numobjs, ...);
+extern void insert_jsonb_key(JsonbParseState *state, char *name);
+
+extern void deparse_ColumnDef_toJsonb(JsonbParseState *state,
+ Relation relation, List *dpcontext,
+ bool composite, ColumnDef *coldef,
+ bool is_alter);
+extern void deparse_ColumnIdentity_toJsonb(JsonbParseState *state,
+ char *parentKey, Oid seqrelid,
+ char identity, bool alter_table);
+extern void deparse_RelSetOptions_toJsonb(JsonbParseState *state,
+ AlterTableCmd *subcmd);
+extern void deparse_ColumnSetOptions_ToJsonb(JsonbParseState *state,
+ AlterTableCmd *subcmd);
+extern char *RelationGetColumnDefault(Relation rel, AttrNumber attno,
+ List *dpcontext);
+extern void new_jsonb_for_qualname_id(JsonbParseState *state, Oid classId,
+ Oid objectId, char *keyName,
+ bool createObject);
+extern char *RelationGetPartitionBound(Oid relid);
+extern void new_jsonb_for_type(JsonbParseState *state, char *parentKey,
+ Oid typId, int32 typmod);
+extern void insert_collate_object(JsonbParseState *state, char *parentKey,
+ char *fmt, Oid classId, Oid objectId,
+ char *key);
+extern void insert_identity_object(JsonbParseState *state, Oid nspid,
+ char *relname);
+extern bool add_table_elems_if_any(JsonbParseState *state, StringInfo fmtStr,
+ Relation relation, List *tableElts,
+ List *dpcontext, Oid objectId, bool typed,
+ bool composite);
+extern void new_jsonbArray_for_qualname_id(JsonbParseState *state,
+ char *keyname, List *array);
+extern void role_to_jsonb_element(JsonbParseState *state, char *owner);
+extern char *get_persistence_str(char persistence);
+extern void deparse_withObj_ToJsonb(JsonbParseState *state, CreateStmt *node);
+extern List *deparse_InhRels_ToJsonb(Oid objectId);
extern char *deparse_utility_command(CollectedCommand *cmd);
extern char *deparse_ddl_json_to_string(char *jsonb);
+extern Jsonb *deparse_create_table(Oid objectId, Node *parsetree);
extern char *deparse_drop_table(const char *objidentity, const char *objecttype,
- Node *parsetree);
+ Node *parsetree);
+extern Jsonb *deparse_AlterTableStmt(CollectedCommand *cmd);
#endif /* DDL_DEPARSE_H */
--
2.34.1