}
}
+/*
+ * Form an ObjElem to be used as a single argument in an aggregate argument
+ * list
+ */
+static ObjElem *
+form_agg_argument(int idx, char *modes, char **names, Oid *types)
+{
+ ObjTree *arg;
+
+ arg = new_objtree_VA("%{mode}s %{name}s %{type}T", 0);
+
+ append_string_object(arg, "mode",
+ (modes && modes[idx] == 'v') ? "VARIADIC" : "");
+ append_string_object(arg, "name", names ? names[idx] : "");
+ append_object_object(arg, "type",
+ new_objtree_for_type(types[idx], -1));
+
+ return new_object_object(arg);
+}
+
+static ObjTree *
+deparse_DefineStmt_Aggregate(Oid objectId, DefineStmt *define)
+{
+ HeapTuple aggTup;
+ HeapTuple procTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ List *list;
+ Datum initval;
+ bool isnull;
+ Form_pg_aggregate agg;
+ Form_pg_proc proc;
+
+ aggTup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(aggTup))
+ elog(ERROR, "cache lookup failed for aggregate with OID %u", objectId);
+ agg = (Form_pg_aggregate) GETSTRUCT(aggTup);
+
+ procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(agg->aggfnoid));
+ if (!HeapTupleIsValid(procTup))
+ elog(ERROR, "cache lookup failed for procedure with OID %u",
+ agg->aggfnoid);
+ proc = (Form_pg_proc) GETSTRUCT(procTup);
+
+ stmt = new_objtree_VA("CREATE AGGREGATE %{identity}D(%{types}s) "
+ "(%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(proc->pronamespace,
+ NameStr(proc->proname)));
+
+ /*
+ * Add the argument list. There are three cases to consider:
+ *
+ * 1. no arguments, in which case the signature is (*).
+ *
+ * 2. Not an ordered-set aggregate. In this case there's one or more
+ * arguments.
+ *
+ * 3. Ordered-set aggregates. These have zero or more direct arguments, and
+ * one or more ordered arguments.
+ *
+ * We don't need to consider default values or table parameters, and the
+ * only mode that we need to consider is VARIADIC.
+ */
+
+ if (proc->pronargs == 0)
+ {
+ append_string_object(stmt, "agg type", "noargs");
+ append_string_object(stmt, "types", "*");
+ }
+ else if (!AGGKIND_IS_ORDERED_SET(agg->aggkind))
+ {
+ int i;
+ int nargs;
+ Oid *types;
+ char *modes;
+ char **names;
+
+ nargs = get_func_arg_info(procTup, &types, &names, &modes);
+
+ /* only direct arguments in this case */
+ list = NIL;
+ for (i = 0; i < nargs; i++)
+ {
+ list = lappend(list, form_agg_argument(i, modes, names, types));
+ }
+
+ tmp = new_objtree_VA("%{direct:, }s", 1,
+ "direct", ObjTypeArray, list);
+ append_object_object(stmt, "types", tmp);
+ append_string_object(stmt, "agg type", "plain");
+ }
+ else
+ {
+ int i;
+ int nargs;
+ Oid *types;
+ char *modes;
+ char **names;
+
+ nargs = get_func_arg_info(procTup, &types, &names, &modes);
+
+ tmp = new_objtree_VA("%{direct:, }s ORDER BY %{aggregated:, }s", 0);
+
+ /* direct arguments ... */
+ list = NIL;
+ for (i = 0; i < agg->aggnumdirectargs; i++)
+ {
+ list = lappend(list, form_agg_argument(i, modes, names, types));
+ }
+ append_array_object(tmp, "direct", list);
+
+ /*
+ * ... and aggregated arguments. If the last direct argument is
+ * VARIADIC, we need to repeat it here rather than searching for more
+ * arguments. (See aggr_args production in gram.y for an explanation.)
+ */
+ if (modes && modes[agg->aggnumdirectargs - 1] == 'v')
+ {
+ list = list_make1(form_agg_argument(agg->aggnumdirectargs - 1,
+ modes, names, types));
+ }
+ else
+ {
+ list = NIL;
+ for (i = agg->aggnumdirectargs; i < nargs; i++)
+ {
+ list = lappend(list, form_agg_argument(i, modes, names, types));
+ }
+ }
+ append_array_object(tmp, "aggregated", list);
+
+ append_object_object(stmt, "types", tmp);
+ append_string_object(stmt, "agg type", "ordered-set");
+ }
+
+ /*
+ * Now add the definition clause
+ */
+ list = NIL;
+
+ tmp = new_objtree_VA("SFUNC=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ agg->aggtransfn));
+ list = lappend(list, new_object_object(tmp));
+
+ tmp = new_objtree_VA("STYPE=%{type}T", 0);
+ append_object_object(tmp, "type",
+ new_objtree_for_type(agg->aggtranstype, -1));
+ list = lappend(list, new_object_object(tmp));
+
+ if (agg->aggtransspace != 0)
+ {
+ tmp = new_objtree_VA("SSPACE=%{space}n", 1,
+ "space", ObjTypeInteger,
+ agg->aggtransspace);
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(agg->aggfinalfn))
+ {
+ tmp = new_objtree_VA("FINALFUNC=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ agg->aggfinalfn));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (agg->aggfinalextra)
+ {
+ tmp = new_objtree_VA("FINALFUNC_EXTRA=true", 0);
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ initval = SysCacheGetAttr(AGGFNOID, aggTup,
+ Anum_pg_aggregate_agginitval,
+ &isnull);
+ if (!isnull)
+ {
+ tmp = new_objtree_VA("INITCOND=%{initval}L",
+ 1, "initval", ObjTypeString,
+ TextDatumGetCString(initval));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(agg->aggmtransfn))
+ {
+ tmp = new_objtree_VA("MSFUNC=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ agg->aggmtransfn));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(agg->aggmtranstype))
+ {
+ tmp = new_objtree_VA("MSTYPE=%{type}T", 0);
+ append_object_object(tmp, "type",
+ new_objtree_for_type(agg->aggmtranstype, -1));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (agg->aggmtransspace != 0)
+ {
+ tmp = new_objtree_VA("MSSPACE=%{space}n", 1,
+ "space", ObjTypeInteger,
+ agg->aggmtransspace);
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(agg->aggminvtransfn))
+ {
+ tmp = new_objtree_VA("MINVFUNC=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ agg->aggminvtransfn));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(agg->aggmfinalfn))
+ {
+ tmp = new_objtree_VA("MFINALFUNC=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ agg->aggmfinalfn));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (agg->aggmfinalextra)
+ {
+ tmp = new_objtree_VA("MFINALFUNC_EXTRA=true", 0);
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ initval = SysCacheGetAttr(AGGFNOID, aggTup,
+ Anum_pg_aggregate_aggminitval,
+ &isnull);
+ if (!isnull)
+ {
+ tmp = new_objtree_VA("MINITCOND=%{initval}L",
+ 1, "initval", ObjTypeString,
+ TextDatumGetCString(initval));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (agg->aggkind == AGGKIND_HYPOTHETICAL)
+ {
+ tmp = new_objtree_VA("HYPOTHETICAL=true", 0);
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(agg->aggsortop))
+ {
+ Oid sortop = agg->aggsortop;
+ Form_pg_operator op;
+ HeapTuple tup;
+
+ tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(sortop));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for operator with OID %u", sortop);
+ op = (Form_pg_operator) GETSTRUCT(tup);
+
+ tmp = new_objtree_VA("SORTOP=%{operator}D", 0);
+ append_object_object(tmp, "operator",
+ new_objtree_for_qualname(op->oprnamespace,
+ NameStr(op->oprname)));
+ list = lappend(list, new_object_object(tmp));
+
+ ReleaseSysCache(tup);
+ }
+
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(procTup);
+ ReleaseSysCache(aggTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_Collation(Oid objectId, DefineStmt *define)
+{
+ HeapTuple colTup;
+ ObjTree *stmt;
+ Form_pg_collation colForm;
+
+ colTup = SearchSysCache1(COLLOID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(colTup))
+ elog(ERROR, "cache lookup failed for collation with OID %u", objectId);
+ colForm = (Form_pg_collation) GETSTRUCT(colTup);
+
+ stmt = new_objtree_VA("CREATE COLLATION %{identity}D "
+ "(LC_COLLATE = %{collate}L,"
+ " LC_CTYPE = %{ctype}L)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(colForm->collnamespace,
+ NameStr(colForm->collname)));
+ append_string_object(stmt, "collate", NameStr(colForm->collcollate));
+ append_string_object(stmt, "ctype", NameStr(colForm->collctype));
+
+ ReleaseSysCache(colTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_Operator(Oid objectId, DefineStmt *define)
+{
+ HeapTuple oprTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ List *list;
+ Form_pg_operator oprForm;
+
+ oprTup = SearchSysCache1(OPEROID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(oprTup))
+ elog(ERROR, "cache lookup failed for operator with OID %u", objectId);
+ oprForm = (Form_pg_operator) GETSTRUCT(oprTup);
+
+ stmt = new_objtree_VA("CREATE OPERATOR %{identity}O (%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(oprForm->oprnamespace,
+ NameStr(oprForm->oprname)));
+
+ list = NIL;
+
+ tmp = new_objtree_VA("PROCEDURE=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ oprForm->oprcode));
+ list = lappend(list, new_object_object(tmp));
+
+ if (OidIsValid(oprForm->oprleft))
+ {
+ tmp = new_objtree_VA("LEFTARG=%{type}T", 0);
+ append_object_object(tmp, "type",
+ new_objtree_for_type(oprForm->oprleft, -1));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(oprForm->oprright))
+ {
+ tmp = new_objtree_VA("RIGHTARG=%{type}T", 0);
+ append_object_object(tmp, "type",
+ new_objtree_for_type(oprForm->oprright, -1));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(oprForm->oprcom))
+ {
+ tmp = new_objtree_VA("COMMUTATOR=%{oper}D", 0);
+ append_object_object(tmp, "oper",
+ new_objtree_for_qualname_id(OperatorRelationId,
+ oprForm->oprcom));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(oprForm->oprnegate))
+ {
+ tmp = new_objtree_VA("NEGATOR=%{oper}D", 0);
+ append_object_object(tmp, "oper",
+ new_objtree_for_qualname_id(OperatorRelationId,
+ oprForm->oprnegate));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(oprForm->oprrest))
+ {
+ tmp = new_objtree_VA("RESTRICT=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ oprForm->oprrest));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (OidIsValid(oprForm->oprjoin))
+ {
+ tmp = new_objtree_VA("JOIN=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ oprForm->oprjoin));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ if (oprForm->oprcanmerge)
+ list = lappend(list, new_object_object(new_objtree_VA("MERGES", 0)));
+ if (oprForm->oprcanhash)
+ list = lappend(list, new_object_object(new_objtree_VA("HASHES", 0)));
+
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(oprTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_TSConfig(Oid objectId, DefineStmt *define,
+ ObjectAddress copied)
+{
+ HeapTuple tscTup;
+ HeapTuple tspTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ Form_pg_ts_config tscForm;
+ Form_pg_ts_parser tspForm;
+ List *list;
+
+ tscTup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(tscTup))
+ elog(ERROR, "cache lookup failed for text search configuration "
+ "with OID %u", objectId);
+ tscForm = (Form_pg_ts_config) GETSTRUCT(tscTup);
+
+ tspTup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(tscForm->cfgparser));
+ if (!HeapTupleIsValid(tspTup))
+ elog(ERROR, "cache lookup failed for text search parser with OID %u",
+ tscForm->cfgparser);
+ tspForm = (Form_pg_ts_parser) GETSTRUCT(tspTup);
+
+ stmt = new_objtree_VA("CREATE TEXT SEARCH CONFIGURATION %{identity}D "
+ "(%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(tscForm->cfgnamespace,
+ NameStr(tscForm->cfgname)));
+
+ /*
+ * If tsconfig was copied from another one, define it like so.
+ */
+ list = NIL;
+ if (copied.objectId != InvalidOid)
+ {
+ tmp = new_objtree_VA("COPY=%{tsconfig}D", 0);
+ append_object_object(tmp, "tsconfig",
+ new_objtree_for_qualname_id(TSConfigRelationId,
+ copied.objectId));
+ }
+ else
+ {
+ tmp = new_objtree_VA("PARSER=%{parser}D", 0);
+ append_object_object(tmp, "parser",
+ new_objtree_for_qualname(tspForm->prsnamespace,
+ NameStr(tspForm->prsname)));
+ }
+ list = lappend(list, new_object_object(tmp));
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(tspTup);
+ ReleaseSysCache(tscTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_TSParser(Oid objectId, DefineStmt *define)
+{
+ HeapTuple tspTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ List *list;
+ Form_pg_ts_parser tspForm;
+
+ tspTup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(tspTup))
+ elog(ERROR, "cache lookup failed for text search parser with OID %u",
+ objectId);
+ tspForm = (Form_pg_ts_parser) GETSTRUCT(tspTup);
+
+ stmt = new_objtree_VA("CREATE TEXT SEARCH PARSER %{identity}D "
+ "(%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(tspForm->prsnamespace,
+ NameStr(tspForm->prsname)));
+
+ list = NIL;
+
+ tmp = new_objtree_VA("START=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tspForm->prsstart));
+ list = lappend(list, new_object_object(tmp));
+
+ tmp = new_objtree_VA("GETTOKEN=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tspForm->prstoken));
+ list = lappend(list, new_object_object(tmp));
+
+ tmp = new_objtree_VA("END=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tspForm->prsend));
+ list = lappend(list, new_object_object(tmp));
+
+ tmp = new_objtree_VA("LEXTYPES=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tspForm->prslextype));
+ list = lappend(list, new_object_object(tmp));
+
+ if (OidIsValid(tspForm->prsheadline))
+ {
+ tmp = new_objtree_VA("HEADLINE=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tspForm->prsheadline));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(tspTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_TSDictionary(Oid objectId, DefineStmt *define)
+{
+ HeapTuple tsdTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ List *list;
+ Datum options;
+ bool isnull;
+ Form_pg_ts_dict tsdForm;
+
+ tsdTup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(tsdTup))
+ elog(ERROR, "cache lookup failed for text search dictionary "
+ "with OID %u", objectId);
+ tsdForm = (Form_pg_ts_dict) GETSTRUCT(tsdTup);
+
+ stmt = new_objtree_VA("CREATE TEXT SEARCH DICTIONARY %{identity}D "
+ "(%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(tsdForm->dictnamespace,
+ NameStr(tsdForm->dictname)));
+
+ list = NIL;
+
+ tmp = new_objtree_VA("TEMPLATE=%{template}D", 0);
+ append_object_object(tmp, "template",
+ new_objtree_for_qualname_id(TSTemplateRelationId,
+ tsdForm->dicttemplate));
+ list = lappend(list, new_object_object(tmp));
+
+ options = SysCacheGetAttr(TSDICTOID, tsdTup,
+ Anum_pg_ts_dict_dictinitoption,
+ &isnull);
+ if (!isnull)
+ {
+ tmp = new_objtree_VA("%{options}s", 0);
+ append_string_object(tmp, "options", TextDatumGetCString(options));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(tsdTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_TSTemplate(Oid objectId, DefineStmt *define)
+{
+ HeapTuple tstTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ List *list;
+ Form_pg_ts_template tstForm;
+
+ tstTup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(tstTup))
+ elog(ERROR, "cache lookup failed for text search template with OID %u",
+ objectId);
+ tstForm = (Form_pg_ts_template) GETSTRUCT(tstTup);
+
+ stmt = new_objtree_VA("CREATE TEXT SEARCH TEMPLATE %{identity}D "
+ "(%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(tstForm->tmplnamespace,
+ NameStr(tstForm->tmplname)));
+
+ list = NIL;
+
+ if (OidIsValid(tstForm->tmplinit))
+ {
+ tmp = new_objtree_VA("INIT=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tstForm->tmplinit));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ tmp = new_objtree_VA("LEXIZE=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ tstForm->tmpllexize));
+ list = lappend(list, new_object_object(tmp));
+
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(tstTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt_Type(Oid objectId, DefineStmt *define)
+{
+ HeapTuple typTup;
+ ObjTree *stmt;
+ ObjTree *tmp;
+ List *list;
+ char *str;
+ Datum dflt;
+ bool isnull;
+ Form_pg_type typForm;
+
+ typTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(typTup))
+ elog(ERROR, "cache lookup failed for type with OID %u", objectId);
+ typForm = (Form_pg_type) GETSTRUCT(typTup);
+
+ /* Shortcut processing for shell types. */
+ if (!typForm->typisdefined)
+ {
+ stmt = new_objtree_VA("CREATE TYPE %{identity}D", 0);
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(typForm->typnamespace,
+ NameStr(typForm->typname)));
+ ReleaseSysCache(typTup);
+ return stmt;
+ }
+
+ stmt = new_objtree_VA("CREATE TYPE %{identity}D (%{elems:, }s)", 0);
+
+ append_object_object(stmt, "identity",
+ new_objtree_for_qualname(typForm->typnamespace,
+ NameStr(typForm->typname)));
+
+ list = NIL;
+
+ /* INPUT */
+ tmp = new_objtree_VA("INPUT=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typinput));
+ list = lappend(list, new_object_object(tmp));
+
+ /* OUTPUT */
+ tmp = new_objtree_VA("OUTPUT=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typoutput));
+ list = lappend(list, new_object_object(tmp));
+
+ /* RECEIVE */
+ if (OidIsValid(typForm->typreceive))
+ {
+ tmp = new_objtree_VA("RECEIVE=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typreceive));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* SEND */
+ if (OidIsValid(typForm->typsend))
+ {
+ tmp = new_objtree_VA("SEND=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typsend));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* TYPMOD_IN */
+ if (OidIsValid(typForm->typmodin))
+ {
+ tmp = new_objtree_VA("TYPMOD_IN=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typmodin));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* TYPMOD_OUT */
+ if (OidIsValid(typForm->typmodout))
+ {
+ tmp = new_objtree_VA("TYPMOD_OUT=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typmodout));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* ANALYZE */
+ if (OidIsValid(typForm->typanalyze))
+ {
+ tmp = new_objtree_VA("ANALYZE=%{procedure}D", 0);
+ append_object_object(tmp, "procedure",
+ new_objtree_for_qualname_id(ProcedureRelationId,
+ typForm->typanalyze));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* INTERNALLENGTH */
+ if (typForm->typlen == -1)
+ {
+ tmp = new_objtree_VA("INTERNALLENGTH=VARIABLE", 0);
+ }
+ else
+ {
+ tmp = new_objtree_VA("INTERNALLENGTH=%{typlen}n", 1,
+ "typlen", ObjTypeInteger, typForm->typlen);
+ }
+ list = lappend(list, new_object_object(tmp));
+
+ /* PASSEDBYVALUE */
+ if (typForm->typbyval)
+ list = lappend(list, new_object_object(new_objtree_VA("PASSEDBYVALUE", 0)));
+
+ /* ALIGNMENT */
+ tmp = new_objtree_VA("ALIGNMENT=%{align}s", 0);
+ switch (typForm->typalign)
+ {
+ case 'd':
+ str = "pg_catalog.float8";
+ break;
+ case 'i':
+ str = "pg_catalog.int4";
+ break;
+ case 's':
+ str = "pg_catalog.int2";
+ break;
+ case 'c':
+ str = "pg_catalog.bpchar";
+ break;
+ default:
+ elog(ERROR, "invalid alignment %c", typForm->typalign);
+ }
+ append_string_object(tmp, "align", str);
+ list = lappend(list, new_object_object(tmp));
+
+ tmp = new_objtree_VA("STORAGE=%{storage}s", 0);
+ switch (typForm->typstorage)
+ {
+ case 'p':
+ str = "plain";
+ break;
+ case 'e':
+ str = "external";
+ break;
+ case 'x':
+ str = "extended";
+ break;
+ case 'm':
+ str = "main";
+ break;
+ default:
+ elog(ERROR, "invalid storage specifier %c", typForm->typstorage);
+ }
+ append_string_object(tmp, "storage", str);
+ list = lappend(list, new_object_object(tmp));
+
+ /* CATEGORY */
+ tmp = new_objtree_VA("CATEGORY=%{category}L", 0);
+ append_string_object(tmp, "category",
+ psprintf("%c", typForm->typcategory));
+ list = lappend(list, new_object_object(tmp));
+
+ /* PREFERRED */
+ if (typForm->typispreferred)
+ list = lappend(list, new_object_object(new_objtree_VA("PREFERRED=true", 0)));
+
+ /* DEFAULT */
+ dflt = SysCacheGetAttr(TYPEOID, typTup,
+ Anum_pg_type_typdefault,
+ &isnull);
+ if (!isnull)
+ {
+ tmp = new_objtree_VA("DEFAULT=%{default}L", 0);
+ append_string_object(tmp, "default", TextDatumGetCString(dflt));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* ELEMENT */
+ if (OidIsValid(typForm->typelem))
+ {
+ tmp = new_objtree_VA("ELEMENT=%{elem}T", 0);
+ append_object_object(tmp, "elem",
+ new_objtree_for_type(typForm->typelem, -1));
+ list = lappend(list, new_object_object(tmp));
+ }
+
+ /* DELIMITER */
+ tmp = new_objtree_VA("DELIMITER=%{delim}L", 0);
+ append_string_object(tmp, "delim",
+ psprintf("%c", typForm->typdelim));
+ list = lappend(list, new_object_object(tmp));
+
+ /* COLLATABLE */
+ if (OidIsValid(typForm->typcollation))
+ list = lappend(list,
+ new_object_object(new_objtree_VA("COLLATABLE=true", 0)));
+
+ append_array_object(stmt, "elems", list);
+
+ ReleaseSysCache(typTup);
+
+ return stmt;
+}
+
+static ObjTree *
+deparse_DefineStmt(Oid objectId, Node *parsetree, ObjectAddress secondaryObj)
+{
+ DefineStmt *define = (DefineStmt *) parsetree;
+ ObjTree *defStmt;
+
+ switch (define->kind)
+ {
+ case OBJECT_AGGREGATE:
+ defStmt = deparse_DefineStmt_Aggregate(objectId, define);
+ break;
+
+ case OBJECT_COLLATION:
+ defStmt = deparse_DefineStmt_Collation(objectId, define);
+ break;
+
+ case OBJECT_OPERATOR:
+ defStmt = deparse_DefineStmt_Operator(objectId, define);
+ break;
+
+ case OBJECT_TSCONFIGURATION:
+ defStmt = deparse_DefineStmt_TSConfig(objectId, define, secondaryObj);
+ break;
+
+ case OBJECT_TSPARSER:
+ defStmt = deparse_DefineStmt_TSParser(objectId, define);
+ break;
+
+ case OBJECT_TSDICTIONARY:
+ defStmt = deparse_DefineStmt_TSDictionary(objectId, define);
+ break;
+
+ case OBJECT_TSTEMPLATE:
+ defStmt = deparse_DefineStmt_TSTemplate(objectId, define);
+ break;
+
+ case OBJECT_TYPE:
+ defStmt = deparse_DefineStmt_Type(objectId, define);
+ break;
+
+ default:
+ elog(ERROR, "unsupported object kind");
+ return NULL;
+ }
+
+ return defStmt;
+}
+
/*
* deparse_CreateExtensionStmt
* deparse a CreateExtensionStmt
/* other local objects */
case T_DefineStmt:
- elog(ERROR, "unimplemented deparse of %s", CreateCommandTag(parsetree));
+ command = deparse_DefineStmt(objectId, parsetree,
+ cmd->d.simple.secondaryObject);
break;
case T_IndexStmt: