v58-0001-Infrastructure-to-support-DDL-deparsing.patch
application/octet-stream
Filename: v58-0001-Infrastructure-to-support-DDL-deparsing.patch
Type: application/octet-stream
Part: 3
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 v58-0001
Subject: Infrastructure to support DDL deparsing.
| File | + | − |
|---|---|---|
| src/backend/catalog/aclchk.c | 5 | 4 |
| src/backend/catalog/objectaddress.c | 1 | 1 |
| src/backend/commands/collationcmds.c | 9 | 1 |
| src/backend/commands/event_trigger.c | 1 | 39 |
| src/backend/commands/seclabel.c | 3 | 0 |
| src/backend/commands/sequence.c | 33 | 0 |
| src/backend/tcop/utility.c | 90 | 1 |
| src/backend/utils/adt/format_type.c | 1 | 3 |
| src/backend/utils/adt/regproc.c | 53 | 0 |
| src/backend/utils/adt/ruleutils.c | 190 | 68 |
| src/include/commands/collationcmds.h | 2 | 1 |
| src/include/commands/event_trigger.h | 39 | 0 |
| src/include/commands/sequence.h | 1 | 0 |
| src/include/tcop/utility.h | 2 | 0 |
| src/include/utils/aclchk_internal.h | 1 | 0 |
| src/include/utils/acl.h | 2 | 0 |
| src/include/utils/builtins.h | 2 | 0 |
| src/include/utils/ruleutils.h | 19 | 0 |
| src/test/regress/expected/object_address.out | 1 | 1 |
From 2d86b36d78818b17eb315a78fe1e7fe62fb0a2ab Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Tue, 20 Dec 2022 17:45:07 +0530
Subject: [PATCH 1/5] Infrastructure to support DDL deparsing.
Infrastructure to support DDL deparsing.
---
src/backend/catalog/aclchk.c | 9 +-
src/backend/catalog/objectaddress.c | 2 +-
src/backend/commands/collationcmds.c | 10 +-
src/backend/commands/event_trigger.c | 40 +--
src/backend/commands/seclabel.c | 3 +
src/backend/commands/sequence.c | 33 +++
src/backend/tcop/utility.c | 91 ++++++-
src/backend/utils/adt/format_type.c | 4 +-
src/backend/utils/adt/regproc.c | 53 ++++
src/backend/utils/adt/ruleutils.c | 258 ++++++++++++++-----
src/include/commands/collationcmds.h | 3 +-
src/include/commands/event_trigger.h | 39 +++
src/include/commands/sequence.h | 1 +
src/include/tcop/utility.h | 2 +
src/include/utils/acl.h | 2 +
src/include/utils/aclchk_internal.h | 1 +
src/include/utils/builtins.h | 2 +
src/include/utils/ruleutils.h | 19 ++
src/test/regress/expected/object_address.out | 2 +-
19 files changed, 455 insertions(+), 119 deletions(-)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index cdfd637815..ba670bc19c 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -129,7 +129,6 @@ static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
AclMode *col_privileges,
int num_col_privileges);
static AclMode string_to_privilege(const char *privname);
-static const char *privilege_to_string(AclMode privilege);
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
bool all_privs, AclMode privileges,
Oid objectId, Oid grantorId,
@@ -385,11 +384,10 @@ ExecuteGrantStmt(GrantStmt *stmt)
ListCell *cell;
const char *errormsg;
AclMode all_privileges;
+ Oid grantor = InvalidOid;
if (stmt->grantor)
{
- Oid grantor;
-
grantor = get_rolespec_oid(stmt->grantor, false);
/*
@@ -408,6 +406,9 @@ ExecuteGrantStmt(GrantStmt *stmt)
istmt.is_grant = stmt->is_grant;
istmt.objtype = stmt->objtype;
+ /* Copy the grantor id needed for DDL deparsing of Grant */
+ istmt.grantor_uid = grantor;
+
/* Collect the OIDs of the target objects */
switch (stmt->targtype)
{
@@ -2628,7 +2629,7 @@ string_to_privilege(const char *privname)
return 0; /* appease compiler */
}
-static const char *
+const char *
privilege_to_string(AclMode privilege)
{
switch (privilege)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index a1df8b1ddc..cf7a5ae62a 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -5914,7 +5914,7 @@ getObjectIdentityParts(const ObjectAddress *object,
transformType = format_type_be_qualified(transform->trftype);
transformLang = get_language_name(transform->trflang, false);
- appendStringInfo(&buffer, "for %s on language %s",
+ appendStringInfo(&buffer, "for %s language %s",
transformType,
transformLang);
if (objname)
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 81e54e0ce6..3ceb7b252a 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -52,7 +52,8 @@ typedef struct
* CREATE COLLATION
*/
ObjectAddress
-DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
+DefineCollation(ParseState *pstate, List *names, List *parameters,
+ bool if_not_exists, ObjectAddress *from_existing_collid)
{
char *collName;
Oid collNamespace;
@@ -139,6 +140,13 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for collation %u", collid);
+ /*
+ * Make from existing collationid available to callers for statement such as
+ * CREATE COLLATION any_name FROM any_name
+ */
+ if (from_existing_collid && OidIsValid(collid))
+ ObjectAddressSet(*from_existing_collid, CollationRelationId, collid);
+
collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index a3bdc5db07..640c25ff70 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -48,45 +48,7 @@
#include "utils/rel.h"
#include "utils/syscache.h"
-typedef struct EventTriggerQueryState
-{
- /* memory context for this state's objects */
- MemoryContext cxt;
-
- /* sql_drop */
- slist_head SQLDropList;
- bool in_sql_drop;
-
- /* table_rewrite */
- Oid table_rewrite_oid; /* InvalidOid, or set for table_rewrite
- * event */
- int table_rewrite_reason; /* AT_REWRITE reason */
-
- /* Support for command collection */
- bool commandCollectionInhibited;
- CollectedCommand *currentCommand;
- List *commandList; /* list of CollectedCommand; see
- * deparse_utility.h */
- struct EventTriggerQueryState *previous;
-} EventTriggerQueryState;
-
-static EventTriggerQueryState *currentEventTriggerState = NULL;
-
-/* Support for dropped objects */
-typedef struct SQLDropObject
-{
- ObjectAddress address;
- const char *schemaname;
- const char *objname;
- const char *objidentity;
- const char *objecttype;
- List *addrnames;
- List *addrargs;
- bool original;
- bool normal;
- bool istemp;
- slist_node next;
-} SQLDropObject;
+EventTriggerQueryState *currentEventTriggerState = NULL;
static void AlterEventTriggerOwner_internal(Relation rel,
HeapTuple tup,
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index 7ae19b98bb..2713cad569 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -134,6 +134,9 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("must specify provider when multiple security label providers have been loaded")));
provider = (LabelProvider *) linitial(label_provider_list);
+
+ /* Copy the provider name to the parsetree, needed for DDL deparsing of SecLabelStmt */
+ stmt->provider = pstrdup(provider->provider_name);
}
else
{
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index c31c9b891a..89f855edf6 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1708,6 +1708,39 @@ process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
relation_close(tablerel, NoLock);
}
+/*
+ * Return sequence parameters, detailed
+ */
+Form_pg_sequence_data
+get_sequence_values(Oid sequenceId)
+{
+ Buffer buf;
+ SeqTable elm;
+ Relation seqrel;
+ HeapTupleData seqtuple;
+ Form_pg_sequence_data seq;
+ Form_pg_sequence_data retSeq;
+
+ /* Open and AccessShareLock sequence */
+ init_sequence(sequenceId, &elm, &seqrel);
+
+ if (pg_class_aclcheck(sequenceId, GetUserId(),
+ ACL_SELECT | ACL_UPDATE | ACL_USAGE) != ACLCHECK_OK)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied for sequence %s",
+ RelationGetRelationName(seqrel))));
+
+ seq = read_seq_tuple(seqrel, &buf, &seqtuple);
+ retSeq = palloc(sizeof(FormData_pg_sequence_data));
+
+ memcpy(retSeq, seq, sizeof(FormData_pg_sequence_data));
+
+ UnlockReleaseBuffer(buf);
+ relation_close(seqrel, NoLock);
+
+ return retSeq;
+}
/*
* Return sequence parameters in a list of the form created by the parser.
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 247d0816ad..f1215c8e18 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1446,7 +1446,8 @@ ProcessUtilitySlow(ParseState *pstate,
address = DefineCollation(pstate,
stmt->defnames,
stmt->definition,
- stmt->if_not_exists);
+ stmt->if_not_exists,
+ &secondaryObject);
break;
default:
elog(ERROR, "unrecognized define stmt type: %d",
@@ -2196,6 +2197,94 @@ UtilityContainsQuery(Node *parsetree)
}
}
+/*
+ * Return the given object type as a string.
+ */
+const char *
+stringify_objtype(ObjectType objtype, bool isgrant)
+{
+ switch (objtype)
+ {
+ case OBJECT_AGGREGATE:
+ return "AGGREGATE";
+ case OBJECT_CAST:
+ return "CAST";
+ case OBJECT_COLLATION:
+ return "COLLATION";
+ case OBJECT_COLUMN:
+ return isgrant ? "TABLE" : "COLUMN";
+ case OBJECT_CONVERSION:
+ return "CONVERSION";
+ case OBJECT_DATABASE:
+ return "DATABASE";
+ case OBJECT_DOMAIN:
+ return "DOMAIN";
+ case OBJECT_EVENT_TRIGGER:
+ return "EVENT TRIGGER";
+ case OBJECT_EXTENSION:
+ return "EXTENSION";
+ case OBJECT_FDW:
+ return "FOREIGN DATA WRAPPER";
+ case OBJECT_FOREIGN_SERVER:
+ return isgrant ? "FOREIGN SERVER" : "SERVER";
+ case OBJECT_FOREIGN_TABLE:
+ return "FOREIGN TABLE";
+ case OBJECT_FUNCTION:
+ return "FUNCTION";
+ case OBJECT_INDEX:
+ return "INDEX";
+ case OBJECT_LANGUAGE:
+ return "LANGUAGE";
+ case OBJECT_LARGEOBJECT:
+ return "LARGE OBJECT";
+ case OBJECT_MATVIEW:
+ return "MATERIALIZED VIEW";
+ case OBJECT_OPCLASS:
+ return "OPERATOR CLASS";
+ case OBJECT_OPERATOR:
+ return "OPERATOR";
+ case OBJECT_OPFAMILY:
+ return "OPERATOR FAMILY";
+ case OBJECT_POLICY:
+ return "POLICY";
+ case OBJECT_PROCEDURE:
+ return "PROCEDURE";
+ case OBJECT_ROLE:
+ return "ROLE";
+ case OBJECT_ROUTINE:
+ return "ROUTINE";
+ case OBJECT_RULE:
+ return "RULE";
+ case OBJECT_SCHEMA:
+ return "SCHEMA";
+ case OBJECT_SEQUENCE:
+ return "SEQUENCE";
+ case OBJECT_STATISTIC_EXT:
+ return "STATISTICS";
+ case OBJECT_TABLE:
+ return "TABLE";
+ case OBJECT_TABLESPACE:
+ return "TABLESPACE";
+ case OBJECT_TRIGGER:
+ return "TRIGGER";
+ case OBJECT_TSCONFIGURATION:
+ return "TEXT SEARCH CONFIGURATION";
+ case OBJECT_TSDICTIONARY:
+ return "TEXT SEARCH DICTIONARY";
+ case OBJECT_TSPARSER:
+ return "TEXT SEARCH PARSER";
+ case OBJECT_TSTEMPLATE:
+ return "TEXT SEARCH TEMPLATE";
+ case OBJECT_TYPE:
+ return "TYPE";
+ case OBJECT_USER_MAPPING:
+ return "USER MAPPING";
+ case OBJECT_VIEW:
+ return "VIEW";
+ default:
+ elog(ERROR, "unsupported object type %d", objtype);
+ }
+}
/*
* AlterObjectTypeCommandTag
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 2918fdbfb6..491dafba74 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -27,8 +27,6 @@
#include "utils/numeric.h"
#include "utils/syscache.h"
-static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
-
/*
* SQL function: format_type(type_oid, typemod)
@@ -363,7 +361,7 @@ format_type_with_typemod(Oid type_oid, int32 typemod)
/*
* Add typmod decoration to the basic type name
*/
-static char *
+char *
printTypmod(const char *typname, int32 typmod, Oid typmodout)
{
char *res;
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 3635a94633..883604f7e6 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -49,6 +49,8 @@ static bool parseNameAndArgTypes(const char *string, bool allowNone,
List **names, int *nargs, Oid *argtypes,
Node *escontext);
+static void format_procedure_args_internal(Form_pg_proc procform,
+ StringInfo buf, bool force_qualify);
/*****************************************************************************
* USER I/O ROUTINES *
@@ -307,6 +309,29 @@ format_procedure_qualified(Oid procedure_oid)
return format_procedure_extended(procedure_oid, FORMAT_PROC_FORCE_QUALIFY);
}
+/*
+ * format_procedure_args - converts proc OID to "(args)"
+ */
+char *
+format_procedure_args(Oid procedure_oid, bool force_qualify)
+{
+ StringInfoData buf;
+ HeapTuple proctup;
+ Form_pg_proc procform;
+
+ proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
+ if (!HeapTupleIsValid(proctup))
+ elog(ERROR, "cache lookup failed for procedure %u", procedure_oid);
+ procform = (Form_pg_proc) GETSTRUCT(proctup);
+
+ initStringInfo(&buf);
+ format_procedure_args_internal(procform, &buf, force_qualify);
+
+ ReleaseSysCache(proctup);
+
+ return buf.data;
+}
+
/*
* format_procedure_extended - converts procedure OID to "pro_name(args)"
*
@@ -2016,3 +2041,31 @@ parseNameAndArgTypes(const char *string, bool allowNone, List **names,
return true;
}
+
+/*
+ * Append the parenthesized arguments of the given pg_proc row into the output
+ * buffer. force_qualify indicates whether to schema-qualify type names
+ * regardless of visibility.
+ */
+static void
+format_procedure_args_internal(Form_pg_proc procform, StringInfo buf,
+ bool force_qualify)
+{
+ int i;
+ char* (*func[2])(Oid) = {format_type_be, format_type_be_qualified};
+
+ appendStringInfoChar(buf, '(');
+ for (i = 0; i < procform->pronargs; i++)
+ {
+ Oid thisargtype = procform->proargtypes.values[i];
+ char *argtype = NULL;
+
+ if (i > 0)
+ appendStringInfoChar(buf, ',');
+
+ argtype = func[force_qualify](thisargtype);
+ appendStringInfoString(buf, argtype);
+ pfree(argtype);
+ }
+ appendStringInfoChar(buf, ')');
+}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 641df1cabe..f99eba1d70 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -35,6 +35,7 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_rewrite.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
@@ -358,7 +359,6 @@ static int print_function_arguments(StringInfo buf, HeapTuple proctup,
bool print_table_args, bool print_defaults);
static void print_function_rettype(StringInfo buf, HeapTuple proctup);
static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
-static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
Bitmapset *rels_used);
static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
@@ -482,22 +482,15 @@ static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
deparse_context *context);
static void get_tablesample_def(TableSampleClause *tablesample,
deparse_context *context);
-static void get_opclass_name(Oid opclass, Oid actual_datatype,
- StringInfo buf);
static Node *processIndirection(Node *node, deparse_context *context);
static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
static char *get_relation_name(Oid relid);
static char *generate_relation_name(Oid relid, List *namespaces);
static char *generate_qualified_relation_name(Oid relid);
-static char *generate_function_name(Oid funcid, int nargs,
- List *argnames, Oid *argtypes,
- bool has_variadic, bool *use_variadic_p,
- ParseExprKind special_exprkind);
static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
static void add_cast_to(StringInfo buf, Oid typid);
static char *generate_qualified_type_name(Oid typid);
static text *string_to_text(char *str);
-static char *flatten_reloptions(Oid relid);
static void get_reloptions(StringInfo buf, Datum reloptions);
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
@@ -545,6 +538,104 @@ pg_get_ruledef_ext(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(string_to_text(res));
}
+/*
+ * Given a pair of Datum corresponding to a rule's pg_rewrite.ev_qual and
+ * ev_action columns, return their text representation; ev_qual as a single
+ * string in whereClause and ev_action as a List of strings (which might be
+ * NIL, signalling NOTHING) in actions.
+ */
+void
+pg_get_ruledef_detailed(Datum ev_qual, Datum ev_action,
+ char **whereClause, List **actions)
+{
+ int prettyFlags = 0;
+ char *qualstr = TextDatumGetCString(ev_qual);
+ char *actionstr = TextDatumGetCString(ev_action);
+ List *actionNodeList = (List *) stringToNode(actionstr);
+ StringInfoData buf;
+
+ *whereClause = NULL;
+ *actions = NIL;
+ initStringInfo(&buf);
+ if (strlen(qualstr) > 0 && strcmp(qualstr, "<>") != 0)
+ {
+ Node *qual;
+ Query *query;
+ deparse_context context;
+ deparse_namespace dpns;
+
+ qual = stringToNode(qualstr);
+
+ query = (Query *) linitial(actionNodeList);
+ query = getInsertSelectQuery(query, NULL);
+
+ AcquireRewriteLocks(query, false, false);
+
+ context.buf = &buf;
+ context.namespaces = list_make1(&dpns);
+ context.windowClause = NIL;
+ context.windowTList = NIL;
+ context.varprefix = (list_length(query->rtable) != 1);
+ context.prettyFlags = prettyFlags;
+ context.wrapColumn = WRAP_COLUMN_DEFAULT;
+ context.indentLevel = PRETTYINDENT_STD;
+
+ set_deparse_for_query(&dpns, query, NIL);
+
+ get_rule_expr(qual, &context, false);
+
+ *whereClause = pstrdup(buf.data);
+ }
+
+ if (list_length(actionNodeList) > 0)
+ {
+ ListCell *cell;
+
+ foreach(cell, actionNodeList)
+ {
+ Query *query = (Query *) lfirst(cell);
+
+ if (query->commandType == CMD_NOTHING)
+ continue;
+
+ resetStringInfo(&buf);
+ get_query_def(query, &buf, NIL, NULL, true,
+ prettyFlags, WRAP_COLUMN_DEFAULT, 0);
+ *actions = lappend(*actions, pstrdup(buf.data));
+ }
+ }
+}
+
+/*
+ * To get the rewrite rule of a view when the CREATE VIEW command execution is
+ * still in progress: we search the system cache RULERELNAME to get the rewrite
+ * rule of the view as opposed to querying pg_rewrite as in pg_get_viewdef_worker(),
+ * which will return empty result.
+ */
+char *
+pg_get_viewdef_internal(Oid viewoid)
+{
+ StringInfoData buf;
+ Relation pg_rewrite;
+ HeapTuple ruletup;
+ TupleDesc rulettc;
+
+ initStringInfo(&buf);
+ pg_rewrite = table_open(RewriteRelationId, AccessShareLock);
+
+ ruletup = SearchSysCache2(RULERELNAME,
+ ObjectIdGetDatum(viewoid),
+ PointerGetDatum(ViewSelectRuleName));
+ if (!HeapTupleIsValid(ruletup))
+ elog(ERROR, "cache lookup failed for rewrite rule for view with OID %u", viewoid);
+
+ rulettc = pg_rewrite->rd_att;
+ make_viewdef(&buf, ruletup, rulettc, 0, WRAP_COLUMN_DEFAULT);
+ ReleaseSysCache(ruletup);
+ table_close(pg_rewrite, AccessShareLock);
+
+ return buf.data;
+}
static char *
pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
@@ -1015,65 +1106,12 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
if (!isnull)
{
Node *qual;
- char relkind;
- deparse_context context;
- deparse_namespace dpns;
- RangeTblEntry *oldrte;
- RangeTblEntry *newrte;
-
- appendStringInfoString(&buf, "WHEN (");
+ char *qualstr;
qual = stringToNode(TextDatumGetCString(value));
+ qualstr = pg_get_trigger_whenclause(trigrec, qual, pretty);
- relkind = get_rel_relkind(trigrec->tgrelid);
-
- /* Build minimal OLD and NEW RTEs for the rel */
- oldrte = makeNode(RangeTblEntry);
- oldrte->rtekind = RTE_RELATION;
- oldrte->relid = trigrec->tgrelid;
- oldrte->relkind = relkind;
- oldrte->rellockmode = AccessShareLock;
- oldrte->alias = makeAlias("old", NIL);
- oldrte->eref = oldrte->alias;
- oldrte->lateral = false;
- oldrte->inh = false;
- oldrte->inFromCl = true;
-
- newrte = makeNode(RangeTblEntry);
- newrte->rtekind = RTE_RELATION;
- newrte->relid = trigrec->tgrelid;
- newrte->relkind = relkind;
- newrte->rellockmode = AccessShareLock;
- newrte->alias = makeAlias("new", NIL);
- newrte->eref = newrte->alias;
- newrte->lateral = false;
- newrte->inh = false;
- newrte->inFromCl = true;
-
- /* Build two-element rtable */
- memset(&dpns, 0, sizeof(dpns));
- dpns.rtable = list_make2(oldrte, newrte);
- dpns.subplans = NIL;
- dpns.ctes = NIL;
- dpns.appendrels = NULL;
- set_rtable_names(&dpns, NIL, NULL);
- set_simple_column_names(&dpns);
-
- /* Set up context with one-deep namespace stack */
- context.buf = &buf;
- context.namespaces = list_make1(&dpns);
- context.windowClause = NIL;
- context.windowTList = NIL;
- context.varprefix = true;
- context.prettyFlags = GET_PRETTY_FLAGS(pretty);
- context.wrapColumn = WRAP_COLUMN_DEFAULT;
- context.indentLevel = PRETTYINDENT_STD;
- context.special_exprkind = EXPR_KIND_NONE;
- context.appendparents = NULL;
-
- get_rule_expr(qual, &context, false);
-
- appendStringInfoString(&buf, ") ");
+ appendStringInfo(&buf, "WHEN (%s) ", qualstr);
}
appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
@@ -1114,6 +1152,69 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
return buf.data;
}
+/*
+ * Parse back the TriggerWhen clause of a trigger given the pg_trigger record and
+ * the expression tree (in nodeToString() representation) from pg_trigger.tgqual
+ * for the trigger's WHEN condition.
+ */
+char *
+pg_get_trigger_whenclause(Form_pg_trigger trigrec, Node *whenClause, bool pretty)
+{
+ StringInfoData buf;
+ char relkind;
+ deparse_context context;
+ deparse_namespace dpns;
+ RangeTblEntry *oldrte;
+ RangeTblEntry *newrte;
+
+ initStringInfo(&buf);
+
+ relkind = get_rel_relkind(trigrec->tgrelid);
+
+ /* Build minimal OLD and NEW RTEs for the rel */
+ oldrte = makeNode(RangeTblEntry);
+ oldrte->rtekind = RTE_RELATION;
+ oldrte->relid = trigrec->tgrelid;
+ oldrte->relkind = relkind;
+ oldrte->alias = makeAlias("old", NIL);
+ oldrte->eref = oldrte->alias;
+ oldrte->lateral = false;
+ oldrte->inh = false;
+ oldrte->inFromCl = true;
+
+ newrte = makeNode(RangeTblEntry);
+ newrte->rtekind = RTE_RELATION;
+ newrte->relid = trigrec->tgrelid;
+ newrte->relkind = relkind;
+ newrte->alias = makeAlias("new", NIL);
+ newrte->eref = newrte->alias;
+ newrte->lateral = false;
+ newrte->inh = false;
+ newrte->inFromCl = true;
+
+ /* Build two-element rtable */
+ memset(&dpns, 0, sizeof(dpns));
+ dpns.rtable = list_make2(oldrte, newrte);
+ dpns.ctes = NIL;
+ set_rtable_names(&dpns, NIL, NULL);
+ set_simple_column_names(&dpns);
+
+ /* Set up context with one-deep namespace stack */
+ context.buf = &buf;
+ context.namespaces = list_make1(&dpns);
+ context.windowClause = NIL;
+ context.windowTList = NIL;
+ context.varprefix = true;
+ context.prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : PRETTYFLAG_INDENT;
+ context.wrapColumn = WRAP_COLUMN_DEFAULT;
+ context.indentLevel = PRETTYINDENT_STD;
+ context.special_exprkind = EXPR_KIND_NONE;
+
+ get_rule_expr(whenClause, &context, false);
+
+ return buf.data;
+}
+
/* ----------
* pg_get_indexdef - Get the definition of an index
*
@@ -1880,6 +1981,13 @@ pg_get_partkeydef_columns(Oid relid, bool pretty)
return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
}
+/* Internal version that reports the full partition key definition */
+char *
+pg_get_partkeydef_simple(Oid relid)
+{
+ return pg_get_partkeydef_worker(relid, 0, false, false);
+}
+
/*
* Internal workhorse to decompile a partition key definition.
*/
@@ -2131,6 +2239,15 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(string_to_text(res));
}
+/*
+ * Internal version that returns the definition of a CONSTRAINT command
+ */
+char *
+pg_get_constraintdef_command_simple(Oid constraintId)
+{
+ return pg_get_constraintdef_worker(constraintId, false, 0, false);
+}
+
/*
* Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
*/
@@ -3501,7 +3618,12 @@ pg_get_function_arg_default(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(string_to_text(str));
}
-static void
+/*
+ * Produce the formatted SQL body (not the whole function definition)
+ * of a function given the pg_proc tuple. Save the formatted SQL in the
+ * given StringInfo.
+ */
+void
print_function_sqlbody(StringInfo buf, HeapTuple proctup)
{
int numargs;
@@ -11357,7 +11479,7 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
* actual_datatype. (If you don't want this behavior, just pass
* InvalidOid for actual_datatype.)
*/
-static void
+void
get_opclass_name(Oid opclass, Oid actual_datatype,
StringInfo buf)
{
@@ -11751,7 +11873,7 @@ generate_qualified_relation_name(Oid relid)
*
* The result includes all necessary quoting and schema-prefixing.
*/
-static char *
+char *
generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
bool has_variadic, bool *use_variadic_p,
ParseExprKind special_exprkind)
@@ -12137,7 +12259,7 @@ get_reloptions(StringInfo buf, Datum reloptions)
/*
* Generate a C string representing a relation's reloptions, or NULL if none.
*/
-static char *
+char *
flatten_reloptions(Oid relid)
{
char *result = NULL;
diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
index 201b19f8b7..46d183760a 100644
--- a/src/include/commands/collationcmds.h
+++ b/src/include/commands/collationcmds.h
@@ -18,7 +18,8 @@
#include "catalog/objectaddress.h"
#include "parser/parse_node.h"
-extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists);
+extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters,
+ bool if_not_exists, ObjectAddress *from_collid);
extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
extern ObjectAddress AlterCollation(AlterCollationStmt *stmt);
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 10091c3aaf..47094752e9 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -16,6 +16,7 @@
#include "catalog/dependency.h"
#include "catalog/objectaddress.h"
#include "catalog/pg_event_trigger.h"
+#include "lib/ilist.h"
#include "nodes/parsenodes.h"
#include "tcop/cmdtag.h"
#include "tcop/deparse_utility.h"
@@ -29,6 +30,44 @@ typedef struct EventTriggerData
CommandTag tag;
} EventTriggerData;
+typedef struct EventTriggerQueryState
+{
+ /* memory context for this state's objects */
+ MemoryContext cxt;
+
+ /* sql_drop */
+ slist_head SQLDropList;
+ bool in_sql_drop;
+
+ /* table_rewrite */
+ Oid table_rewrite_oid; /* InvalidOid, or set for table_rewrite
+ * event */
+ int table_rewrite_reason; /* AT_REWRITE reason */
+
+ /* Support for command collection */
+ bool commandCollectionInhibited;
+ CollectedCommand *currentCommand;
+ List *commandList; /* list of CollectedCommand; see
+ * deparse_utility.h */
+ struct EventTriggerQueryState *previous;
+} EventTriggerQueryState;
+
+/* Support for dropped objects */
+typedef struct SQLDropObject
+{
+ ObjectAddress address;
+ const char *schemaname;
+ const char *objname;
+ const char *objidentity;
+ const char *objecttype;
+ List *addrnames;
+ List *addrargs;
+ bool original;
+ bool normal;
+ bool istemp;
+ slist_node next;
+} SQLDropObject;
+
#define AT_REWRITE_ALTER_PERSISTENCE 0x01
#define AT_REWRITE_DEFAULT_VAL 0x02
#define AT_REWRITE_COLUMN_REWRITE 0x04
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
index b3b04ccfa9..c2b1ca32f6 100644
--- a/src/include/commands/sequence.h
+++ b/src/include/commands/sequence.h
@@ -54,6 +54,7 @@ typedef struct xl_seq_rec
extern int64 nextval_internal(Oid relid, bool check_permissions);
extern Datum nextval(PG_FUNCTION_ARGS);
extern List *sequence_options(Oid relid);
+extern Form_pg_sequence_data get_sequence_values(Oid sequenceId);
extern ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *seq);
extern ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt);
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
index f9daf5b744..f92bbf8843 100644
--- a/src/include/tcop/utility.h
+++ b/src/include/tcop/utility.h
@@ -99,6 +99,8 @@ extern Query *UtilityContainsQuery(Node *parsetree);
extern CommandTag CreateCommandTag(Node *parsetree);
+extern const char *stringify_objtype(ObjectType objtype, bool isgrant);
+
static inline const char *
CreateCommandName(Node *parsetree)
{
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 69eb437376..c0e202b44e 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -209,6 +209,8 @@ extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
AclMode mask, AclMaskHow how);
extern int aclmembers(const Acl *acl, Oid **roleids);
+extern const char *privilege_to_string(AclMode privilege);
+
extern bool has_privs_of_role(Oid member, Oid role);
extern bool member_can_set_role(Oid member, Oid role);
extern void check_can_set_role(Oid member, Oid role);
diff --git a/src/include/utils/aclchk_internal.h b/src/include/utils/aclchk_internal.h
index 361284d8eb..4e020ef4ae 100644
--- a/src/include/utils/aclchk_internal.h
+++ b/src/include/utils/aclchk_internal.h
@@ -39,6 +39,7 @@ typedef struct
List *grantees;
bool grant_option;
DropBehavior behavior;
+ Oid grantor_uid;
} InternalGrant;
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index a4a20b5a45..9bfe08589f 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -123,10 +123,12 @@ extern Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS);
#define FORMAT_TYPE_FORCE_QUALIFY 0x04 /* force qualification of type */
#define FORMAT_TYPE_INVALID_AS_NULL 0x08 /* NULL if undefined */
extern char *format_type_extended(Oid type_oid, int32 typemod, bits16 flags);
+extern char *format_procedure_args(Oid procedure_oid, bool force_qualify);
extern char *format_type_be(Oid type_oid);
extern char *format_type_be_qualified(Oid type_oid);
extern char *format_type_with_typemod(Oid type_oid, int32 typemod);
+extern char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
extern int32 type_maximum_size(Oid type_oid, int32 typemod);
diff --git a/src/include/utils/ruleutils.h b/src/include/utils/ruleutils.h
index 7d489718a3..ec6ef80164 100644
--- a/src/include/utils/ruleutils.h
+++ b/src/include/utils/ruleutils.h
@@ -13,9 +13,12 @@
#ifndef RULEUTILS_H
#define RULEUTILS_H
+#include "access/htup.h"
+#include "catalog/pg_trigger.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
+#include "parser/parse_node.h"
struct Plan; /* avoid including plannodes.h here */
struct PlannedStmt;
@@ -23,12 +26,20 @@ struct PlannedStmt;
extern char *pg_get_indexdef_string(Oid indexrelid);
extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty);
+extern char *pg_get_trigger_whenclause(Form_pg_trigger trigrec,
+ Node *whenClause, bool pretty);
extern char *pg_get_querydef(Query *query, bool pretty);
+extern char *pg_get_viewdef_internal(Oid viewoid);
extern char *pg_get_partkeydef_columns(Oid relid, bool pretty);
+extern char *pg_get_partkeydef_simple(Oid relid);
extern char *pg_get_partconstrdef_string(Oid partitionId, char *aliasname);
extern char *pg_get_constraintdef_command(Oid constraintId);
+extern char *pg_get_constraintdef_command_simple(Oid constraintId);
+extern void pg_get_ruledef_detailed(Datum ev_qual, Datum ev_action,
+ char **whereClause, List **actions);
+
extern char *deparse_expression(Node *expr, List *dpcontext,
bool forceprefix, bool showimplicit);
extern List *deparse_context_for(const char *aliasname, Oid relid);
@@ -40,8 +51,16 @@ extern List *select_rtable_names_for_explain(List *rtable,
Bitmapset *rels_used);
extern char *generate_collation_name(Oid collid);
extern char *generate_opclass_name(Oid opclass);
+extern char *generate_function_name(Oid funcid, int nargs, List *argnames,
+ Oid *argtypes, bool has_variadic,
+ bool *use_variadic_p,
+ ParseExprKind special_exprkind);
extern char *get_range_partbound_string(List *bound_datums);
+extern void get_opclass_name(Oid opclass, Oid actual_datatype,
+ StringInfo buf);
+extern char *flatten_reloptions(Oid relid);
extern char *pg_get_statisticsobjdef_string(Oid statextid);
+extern void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
#endif /* RULEUTILS_H */
diff --git a/src/test/regress/expected/object_address.out b/src/test/regress/expected/object_address.out
index 25c174f275..fc42d418bf 100644
--- a/src/test/regress/expected/object_address.out
+++ b/src/test/regress/expected/object_address.out
@@ -496,7 +496,7 @@ operator family|pg_catalog|integer_ops|pg_catalog.integer_ops USING btree|t
policy|NULL|NULL|genpol on addr_nsp.gentable|t
statistics object|addr_nsp|gentable_stat|addr_nsp.gentable_stat|t
collation|pg_catalog|"default"|pg_catalog."default"|t
-transform|NULL|NULL|for integer on language sql|t
+transform|NULL|NULL|for integer language sql|t
text search dictionary|addr_nsp|addr_ts_dict|addr_nsp.addr_ts_dict|t
text search parser|addr_nsp|addr_ts_prs|addr_nsp.addr_ts_prs|t
text search configuration|addr_nsp|addr_ts_conf|addr_nsp.addr_ts_conf|t
--
2.38.1