At 2016-03-24 12:31:16 -0300, [email protected] wrote:
>
> In other words I think the conclusion here is that we must use
> qualified_name in the new production rather than switching the old
> production to any_name.
Makes sense.
> I think I would like to see code implement both alternatives to see
> which one is least ugly. Maybe a third idea will manifest itself upon
> seeing those.
Here's the first one. ExecAlterObjectDependsStmt() looks like this:
+ObjectAddress
+ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt)
+{
+ ObjectAddress address;
+ ObjectAddress extAddr;
+ Relation rel = NULL;
+
+ /*
+ * If the parser handed us a RangeVar, we add the relation's name to
+ * stmt->objname so that we can pass it to get_object_address().
+ */
+ if (stmt->relation)
+ {
+ stmt->objname = lcons(makeString(stmt->relation->relname),
stmt->objname);
+ if (stmt->relation->schemaname)
+ stmt->objname = lcons(makeString(stmt->relation->schemaname),
stmt->objname);
+ if (stmt->relation->catalogname)
+ stmt->objname = lcons(makeString(stmt->relation->catalogname),
stmt->objname);
+ }
+
+ address = get_object_address(stmt->objectType, stmt->objname,
stmt->objargs,
+ &rel, AccessExclusiveLock, false);
+
+ if (rel)
+ heap_close(rel, NoLock);
+
+ extAddr = get_object_address(OBJECT_EXTENSION, stmt->extname, NULL,
+ &rel, AccessExclusiveLock, false);
+
+ recordDependencyOn(&address, &extAddr, DEPENDENCY_AUTO_EXTENSION);
+
+ return address;
+}
(This works fine for both functions and triggers, I tested it.)
Complete patch attached for reference.
I'll post the get_object_address_rv() variant tomorrow, but comments are
welcome in the meantime.
-- Abhijit
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 951f59b..189b771 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -2864,6 +2864,19 @@
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><symbol>DEPENDENCY_AUTO_EXTENSION</> (<literal>x</>)</term>
+ <listitem>
+ <para>
+ The dependent object is not a member of the extension that is the
+ referenced object (and so should not be ignored by pg_dump), but
+ cannot function without it and should be dropped when the
+ extension itself is. The dependent object may be dropped on its
+ own as well.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
Other dependency flavors might be needed in future.
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index c48e37b..a284bed 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -587,6 +587,7 @@ findDependentObjects(const ObjectAddress *object,
{
case DEPENDENCY_NORMAL:
case DEPENDENCY_AUTO:
+ case DEPENDENCY_AUTO_EXTENSION:
/* no problem */
break;
case DEPENDENCY_INTERNAL:
@@ -786,6 +787,7 @@ findDependentObjects(const ObjectAddress *object,
subflags = DEPFLAG_NORMAL;
break;
case DEPENDENCY_AUTO:
+ case DEPENDENCY_AUTO_EXTENSION:
subflags = DEPFLAG_AUTO;
break;
case DEPENDENCY_INTERNAL:
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 5af0f2f..339a313 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -23,6 +23,7 @@
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_event_trigger.h"
+#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
@@ -32,6 +33,7 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
@@ -391,6 +393,45 @@ ExecRenameStmt(RenameStmt *stmt)
}
/*
+ * Executes an ALTER OBJECT / DEPENDS ON EXTENSION statement.
+ *
+ * Return value is the address of the altered object.
+ */
+ObjectAddress
+ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt)
+{
+ ObjectAddress address;
+ ObjectAddress extAddr;
+ Relation rel = NULL;
+
+ /*
+ * If the parser handed us a RangeVar, we add the relation's name to
+ * stmt->objname so that we can pass it to get_object_address().
+ */
+ if (stmt->relation)
+ {
+ stmt->objname = lcons(makeString(stmt->relation->relname), stmt->objname);
+ if (stmt->relation->schemaname)
+ stmt->objname = lcons(makeString(stmt->relation->schemaname), stmt->objname);
+ if (stmt->relation->catalogname)
+ stmt->objname = lcons(makeString(stmt->relation->catalogname), stmt->objname);
+ }
+
+ address = get_object_address(stmt->objectType, stmt->objname, stmt->objargs,
+ &rel, AccessExclusiveLock, false);
+
+ if (rel)
+ heap_close(rel, NoLock);
+
+ extAddr = get_object_address(OBJECT_EXTENSION, stmt->extname, NULL,
+ &rel, AccessExclusiveLock, false);
+
+ recordDependencyOn(&address, &extAddr, DEPENDENCY_AUTO_EXTENSION);
+
+ return address;
+}
+
+/*
* Executes an ALTER OBJECT / SET SCHEMA statement. Based on the object
* type, the function appropriate to that type is executed.
*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 6b5d1d6..ecc260d 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3203,6 +3203,20 @@ _copyRenameStmt(const RenameStmt *from)
return newnode;
}
+static AlterObjectDependsStmt *
+_copyAlterObjectDependsStmt(const AlterObjectDependsStmt *from)
+{
+ AlterObjectDependsStmt *newnode = makeNode(AlterObjectDependsStmt);
+
+ COPY_SCALAR_FIELD(objectType);
+ COPY_NODE_FIELD(relation);
+ COPY_NODE_FIELD(objname);
+ COPY_NODE_FIELD(objargs);
+ COPY_NODE_FIELD(extname);
+
+ return newnode;
+}
+
static AlterObjectSchemaStmt *
_copyAlterObjectSchemaStmt(const AlterObjectSchemaStmt *from)
{
@@ -4669,6 +4683,9 @@ copyObject(const void *from)
case T_RenameStmt:
retval = _copyRenameStmt(from);
break;
+ case T_AlterObjectDependsStmt:
+ retval = _copyAlterObjectDependsStmt(from);
+ break;
case T_AlterObjectSchemaStmt:
retval = _copyAlterObjectSchemaStmt(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 87eb859..6db0bba 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1326,6 +1326,18 @@ _equalRenameStmt(const RenameStmt *a, const RenameStmt *b)
}
static bool
+_equalAlterObjectDependsStmt(const AlterObjectDependsStmt *a, const AlterObjectDependsStmt *b)
+{
+ COMPARE_SCALAR_FIELD(objectType);
+ COMPARE_NODE_FIELD(relation);
+ COMPARE_NODE_FIELD(objname);
+ COMPARE_NODE_FIELD(objargs);
+ COMPARE_NODE_FIELD(extname);
+
+ return true;
+}
+
+static bool
_equalAlterObjectSchemaStmt(const AlterObjectSchemaStmt *a, const AlterObjectSchemaStmt *b)
{
COMPARE_SCALAR_FIELD(objectType);
@@ -2994,6 +3006,9 @@ equal(const void *a, const void *b)
case T_RenameStmt:
retval = _equalRenameStmt(a, b);
break;
+ case T_AlterObjectDependsStmt:
+ retval = _equalAlterObjectDependsStmt(a, b);
+ break;
case T_AlterObjectSchemaStmt:
retval = _equalAlterObjectSchemaStmt(a, b);
break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a74fb77..2ff409e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -232,7 +232,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
AlterEventTrigStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
- AlterObjectSchemaStmt AlterOwnerStmt AlterOperatorStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
+ AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt
+ AlterOperatorStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt AlterPolicyStmt
@@ -577,7 +578,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
- DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC
+ DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DEPENDS DESC
DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT
@@ -766,6 +767,7 @@ stmt :
| AlterForeignTableStmt
| AlterFunctionStmt
| AlterGroupStmt
+ | AlterObjectDependsStmt
| AlterObjectSchemaStmt
| AlterOwnerStmt
| AlterOperatorStmt
@@ -8007,6 +8009,35 @@ opt_set_data: SET DATA_P { $$ = 1; }
/*****************************************************************************
*
+ * ALTER THING name DEPENDS ON EXTENSION name
+ *
+ *****************************************************************************/
+
+AlterObjectDependsStmt:
+ ALTER FUNCTION function_with_argtypes DEPENDS ON EXTENSION name
+ {
+ AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
+ n->objectType = OBJECT_FUNCTION;
+ n->relation = NULL;
+ n->objname = $3->funcname;
+ n->objargs = $3->funcargs;
+ n->extname = list_make1(makeString($7));
+ $$ = (Node *)n;
+ }
+ | ALTER TRIGGER name ON qualified_name DEPENDS ON EXTENSION name
+ {
+ AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
+ n->objectType = OBJECT_TRIGGER;
+ n->relation = $5;
+ n->objname = list_make1(makeString($3));
+ n->objargs = NIL;
+ n->extname = list_make1(makeString($9));
+ $$ = (Node *)n;
+ }
+ ;
+
+/*****************************************************************************
+ *
* ALTER THING name SET SCHEMA name
*
*****************************************************************************/
@@ -13706,6 +13737,7 @@ unreserved_keyword:
| DELETE_P
| DELIMITER
| DELIMITERS
+ | DEPENDS
| DICTIONARY
| DISABLE_P
| DISCARD
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 045f7f0..16c6a77 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -147,6 +147,7 @@ check_xact_readonly(Node *parsetree)
case T_AlterFunctionStmt:
case T_AlterRoleStmt:
case T_AlterRoleSetStmt:
+ case T_AlterObjectDependsStmt:
case T_AlterObjectSchemaStmt:
case T_AlterOwnerStmt:
case T_AlterOperatorStmt:
@@ -836,6 +837,19 @@ standard_ProcessUtility(Node *parsetree,
}
break;
+ case T_AlterObjectDependsStmt:
+ {
+ AlterObjectDependsStmt *stmt = (AlterObjectDependsStmt *) parsetree;
+
+ if (EventTriggerSupportsObjectType(stmt->objectType))
+ ProcessUtilitySlow(parsetree, queryString,
+ context, params,
+ dest, completionTag);
+ else
+ ExecAlterObjectDependsStmt(stmt);
+ }
+ break;
+
case T_AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
@@ -1472,6 +1486,11 @@ ProcessUtilitySlow(Node *parsetree,
address = ExecRenameStmt((RenameStmt *) parsetree);
break;
+ case T_AlterObjectDependsStmt:
+ address =
+ ExecAlterObjectDependsStmt((AlterObjectDependsStmt *) parsetree);
+ break;
+
case T_AlterObjectSchemaStmt:
address =
ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
@@ -2185,6 +2204,10 @@ CreateCommandTag(Node *parsetree)
tag = AlterObjectTypeCommandTag(((RenameStmt *) parsetree)->renameType);
break;
+ case T_AlterObjectDependsStmt:
+ tag = AlterObjectTypeCommandTag(((AlterObjectDependsStmt *) parsetree)->objectType);
+ break;
+
case T_AlterObjectSchemaStmt:
tag = AlterObjectTypeCommandTag(((AlterObjectSchemaStmt *) parsetree)->objectType);
break;
@@ -2808,6 +2831,10 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_DDL;
break;
+ case T_AlterObjectDependsStmt:
+ lev = LOGSTMT_DDL;
+ break;
+
case T_AlterObjectSchemaStmt:
lev = LOGSTMT_DDL;
break;
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 049bf9f..380f74a 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -61,6 +61,12 @@
* created only during initdb. The fields for the dependent object
* contain zeroes.
*
+ * DEPENDENCY_AUTO_EXTENSION ('x'): the dependent object is not a member
+ * of the extension that is the referenced object (and so should not be
+ * ignored by pg_dump), but cannot function without it and should be
+ * dropped when the extension itself is. The dependent object may be
+ * dropped on its own as well.
+ *
* Other dependency flavors may be needed in future.
*/
@@ -70,7 +76,8 @@ typedef enum DependencyType
DEPENDENCY_AUTO = 'a',
DEPENDENCY_INTERNAL = 'i',
DEPENDENCY_EXTENSION = 'e',
- DEPENDENCY_PIN = 'p'
+ DEPENDENCY_PIN = 'p',
+ DEPENDENCY_AUTO_EXTENSION = 'x'
} DependencyType;
/*
diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h
index cf92e3e..6cd1bca 100644
--- a/src/include/commands/alter.h
+++ b/src/include/commands/alter.h
@@ -21,6 +21,7 @@
extern ObjectAddress ExecRenameStmt(RenameStmt *stmt);
+extern ObjectAddress ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt);
extern ObjectAddress ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
ObjectAddress *oldSchemaAddr);
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 42c9582..fbf78bc 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -368,6 +368,7 @@ typedef enum NodeTag
T_DeclareCursorStmt,
T_CreateTableSpaceStmt,
T_DropTableSpaceStmt,
+ T_AlterObjectDependsStmt,
T_AlterObjectSchemaStmt,
T_AlterOwnerStmt,
T_AlterOperatorStmt,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 2fd0629..4f613b8 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2523,6 +2523,21 @@ typedef struct RenameStmt
} RenameStmt;
/* ----------------------
+ * ALTER object DEPENDS ON EXTENSION extname
+ * ----------------------
+ */
+
+typedef struct AlterObjectDependsStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_TYPE, etc */
+ RangeVar *relation; /* in case a table is involved */
+ List *objname; /* name of the object */
+ List *objargs; /* argument types, if applicable */
+ List *extname; /* target extension's name */
+} AlterObjectDependsStmt;
+
+/* ----------------------
* ALTER object SET SCHEMA Statement
* ----------------------
*/
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 6e1e820..709a288 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -125,6 +125,7 @@ PG_KEYWORD("definer", DEFINER, UNRESERVED_KEYWORD)
PG_KEYWORD("delete", DELETE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD)
PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD)
+PG_KEYWORD("depends", DEPENDS, UNRESERVED_KEYWORD)
PG_KEYWORD("desc", DESC, RESERVED_KEYWORD)
PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD)
PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD)
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index c2511de..e293fc0 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -67,6 +67,7 @@ AlterExtensionStmt
AlterFdwStmt
AlterForeignServerStmt
AlterFunctionStmt
+AlterObjectDependsStmt
AlterObjectSchemaStmt
AlterOpFamilyStmt
AlterOwnerStmt
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers