aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/alter_extension.sgml15
-rw-r--r--src/backend/catalog/pg_depend.c86
-rw-r--r--src/backend/commands/extension.c58
-rw-r--r--src/backend/nodes/copyfuncs.c11
-rw-r--r--src/backend/nodes/equalfuncs.c7
-rw-r--r--src/backend/parser/gram.y113
-rw-r--r--src/backend/tcop/utility.c10
-rw-r--r--src/bin/psql/tab-complete.c7
-rw-r--r--src/include/catalog/dependency.h3
-rw-r--r--src/include/commands/extension.h2
-rw-r--r--src/include/nodes/nodes.h2
-rw-r--r--src/include/nodes/parsenodes.h5
12 files changed, 207 insertions, 112 deletions
diff --git a/doc/src/sgml/ref/alter_extension.sgml b/doc/src/sgml/ref/alter_extension.sgml
index 6613418fd23..e9eb1aafbb6 100644
--- a/doc/src/sgml/ref/alter_extension.sgml
+++ b/doc/src/sgml/ref/alter_extension.sgml
@@ -25,6 +25,7 @@ PostgreSQL documentation
<synopsis>
ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD <replaceable class="PARAMETER">member_object</replaceable>
+ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> DROP <replaceable class="PARAMETER">member_object</replaceable>
<phrase>where <replaceable class="PARAMETER">member_object</replaceable> is:</phrase>
@@ -82,6 +83,17 @@ ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>DROP <replaceable class="PARAMETER">member_object</replaceable></literal></term>
+ <listitem>
+ <para>
+ This form removes a member object from the extension. This is mainly
+ useful in extension upgrade scripts. The object is not dropped, only
+ disassociated from the extension.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
See <xref linkend="extend-extensions"> for more information about these
@@ -123,7 +135,8 @@ ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD
<term><replaceable class="parameter">operator_name</replaceable></term>
<listitem>
<para>
- The name of an object to be added to the extension. Names of tables,
+ The name of an object to be added to or removed from the extension.
+ Names of tables,
aggregates, domains, foreign tables, functions, operators,
operator classes, operator families, sequences, text search objects,
types, and views can be schema-qualified.
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index b2ce148d625..2bb7bb3d5fa 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -200,6 +200,57 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId,
}
/*
+ * deleteDependencyRecordsForClass -- delete all records with given depender
+ * classId/objectId, dependee classId, and deptype.
+ * Returns the number of records deleted.
+ *
+ * This is a variant of deleteDependencyRecordsFor, useful when revoking
+ * an object property that is expressed by a dependency record (such as
+ * extension membership).
+ */
+long
+deleteDependencyRecordsForClass(Oid classId, Oid objectId,
+ Oid refclassId, char deptype)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = heap_open(DependRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ SnapshotNow, 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == refclassId && depform->deptype == deptype)
+ {
+ simple_heap_delete(depRel, &tup->t_self);
+ count++;
+ }
+ }
+
+ systable_endscan(scan);
+
+ heap_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
* Adjust dependency record(s) to point to a different object of the same type
*
* classId/objectId specify the referencing object.
@@ -470,39 +521,8 @@ sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
void
markSequenceUnowned(Oid seqId)
{
- Relation depRel;
- ScanKeyData key[2];
- SysScanDesc scan;
- HeapTuple tup;
-
- depRel = heap_open(DependRelationId, RowExclusiveLock);
-
- ScanKeyInit(&key[0],
- Anum_pg_depend_classid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(RelationRelationId));
- ScanKeyInit(&key[1],
- Anum_pg_depend_objid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(seqId));
-
- scan = systable_beginscan(depRel, DependDependerIndexId, true,
- SnapshotNow, 2, key);
-
- while (HeapTupleIsValid((tup = systable_getnext(scan))))
- {
- Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
-
- if (depform->refclassid == RelationRelationId &&
- depform->deptype == DEPENDENCY_AUTO)
- {
- simple_heap_delete(depRel, &tup->t_self);
- }
- }
-
- systable_endscan(scan);
-
- heap_close(depRel, RowExclusiveLock);
+ deleteDependencyRecordsForClass(RelationRelationId, seqId,
+ RelationRelationId, DEPENDENCY_AUTO);
}
/*
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 1da76aca10f..bc121808bec 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1436,14 +1436,15 @@ AlterExtensionNamespace(List *names, const char *newschema)
}
/*
- * Execute ALTER EXTENSION ADD
+ * Execute ALTER EXTENSION ADD/DROP
*/
void
-ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt)
+ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
{
ObjectAddress extension;
ObjectAddress object;
Relation relation;
+ Oid oldExtension;
/*
* For now, insist on superuser privilege. Later we might want to
@@ -1462,25 +1463,54 @@ ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt)
/*
* Translate the parser representation that identifies the object into
* an ObjectAddress. get_object_address() will throw an error if the
- * object does not exist, and will also acquire a lock on the object
- * to guard against concurrent DROP and ALTER EXTENSION ADD operations.
+ * object does not exist, and will also acquire a lock on the object to
+ * guard against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
*/
object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
&relation, ShareUpdateExclusiveLock);
/*
- * Complain if object is already attached to some extension.
+ * Check existing extension membership.
*/
- if (getExtensionOfObject(object.classId, object.objectId) != InvalidOid)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("%s is already a member of an extension",
- getObjectDescription(&object))));
+ oldExtension = getExtensionOfObject(object.classId, object.objectId);
- /*
- * OK, add the dependency.
- */
- recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
+ if (stmt->action > 0)
+ {
+ /*
+ * ADD, so complain if object is already attached to some extension.
+ */
+ if (OidIsValid(oldExtension))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("%s is already a member of extension \"%s\"",
+ getObjectDescription(&object),
+ get_extension_name(oldExtension))));
+
+ /*
+ * OK, add the dependency.
+ */
+ recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
+ }
+ else
+ {
+ /*
+ * DROP, so complain if it's not a member.
+ */
+ if (oldExtension != extension.objectId)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("%s is not a member of extension \"%s\"",
+ getObjectDescription(&object),
+ stmt->extname)));
+
+ /*
+ * OK, drop the dependency.
+ */
+ if (deleteDependencyRecordsForClass(object.classId, object.objectId,
+ ExtensionRelationId,
+ DEPENDENCY_EXTENSION) != 1)
+ elog(ERROR, "unexpected number of extension dependency records");
+ }
/*
* If get_object_address() opened the relation for us, we close it to keep
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 83630924f63..46acaf8d701 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3251,12 +3251,13 @@ _copyCreateExtensionStmt(CreateExtensionStmt *from)
return newnode;
}
-static AlterExtensionAddStmt *
-_copyAlterExtensionAddStmt(AlterExtensionAddStmt *from)
+static AlterExtensionContentsStmt *
+_copyAlterExtensionContentsStmt(AlterExtensionContentsStmt *from)
{
- AlterExtensionAddStmt *newnode = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *newnode = makeNode(AlterExtensionContentsStmt);
COPY_STRING_FIELD(extname);
+ COPY_SCALAR_FIELD(action);
COPY_SCALAR_FIELD(objtype);
COPY_NODE_FIELD(objname);
COPY_NODE_FIELD(objargs);
@@ -4266,8 +4267,8 @@ copyObject(void *from)
case T_CreateExtensionStmt:
retval = _copyCreateExtensionStmt(from);
break;
- case T_AlterExtensionAddStmt:
- retval = _copyAlterExtensionAddStmt(from);
+ case T_AlterExtensionContentsStmt:
+ retval = _copyAlterExtensionContentsStmt(from);
break;
case T_CreateFdwStmt:
retval = _copyCreateFdwStmt(from);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 9baa7862e6c..2fbe99937d2 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1655,9 +1655,10 @@ _equalCreateExtensionStmt(CreateExtensionStmt *a, CreateExtensionStmt *b)
}
static bool
-_equalAlterExtensionAddStmt(AlterExtensionAddStmt *a, AlterExtensionAddStmt *b)
+_equalAlterExtensionContentsStmt(AlterExtensionContentsStmt *a, AlterExtensionContentsStmt *b)
{
COMPARE_STRING_FIELD(extname);
+ COMPARE_SCALAR_FIELD(action);
COMPARE_SCALAR_FIELD(objtype);
COMPARE_NODE_FIELD(objname);
COMPARE_NODE_FIELD(objargs);
@@ -2868,8 +2869,8 @@ equal(void *a, void *b)
case T_CreateExtensionStmt:
retval = _equalCreateExtensionStmt(a, b);
break;
- case T_AlterExtensionAddStmt:
- retval = _equalAlterExtensionAddStmt(a, b);
+ case T_AlterExtensionContentsStmt:
+ retval = _equalAlterExtensionContentsStmt(a, b);
break;
case T_CreateFdwStmt:
retval = _equalCreateFdwStmt(a, b);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e2d7d6a02f3..82ff9accc72 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -185,7 +185,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
- AlterExtensionAddStmt AlterForeignTableStmt
+ AlterExtensionContentsStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
AlterDefaultPrivilegesStmt DefACLAction
@@ -664,7 +664,7 @@ stmt :
| AlterDefaultPrivilegesStmt
| AlterDomainStmt
| AlterEnumStmt
- | AlterExtensionAddStmt
+ | AlterExtensionContentsStmt
| AlterFdwStmt
| AlterForeignServerStmt
| AlterForeignTableStmt
@@ -3251,181 +3251,202 @@ create_extension_opt_item:
/*****************************************************************************
*
- * ALTER EXTENSION name ADD object-identifier
+ * ALTER EXTENSION name ADD/DROP object-identifier
*
*****************************************************************************/
-AlterExtensionAddStmt:
- ALTER EXTENSION name ADD_P AGGREGATE func_name aggr_args
+AlterExtensionContentsStmt:
+ ALTER EXTENSION name add_drop AGGREGATE func_name aggr_args
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_AGGREGATE;
n->objname = $6;
n->objargs = $7;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P CAST '(' Typename AS Typename ')'
+ | ALTER EXTENSION name add_drop CAST '(' Typename AS Typename ')'
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_CAST;
n->objname = list_make1($7);
n->objargs = list_make1($9);
$$ = (Node *) n;
}
- | ALTER EXTENSION name ADD_P CONVERSION_P any_name
+ | ALTER EXTENSION name add_drop CONVERSION_P any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_CONVERSION;
n->objname = $6;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P DOMAIN_P any_name
+ | ALTER EXTENSION name add_drop DOMAIN_P any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_DOMAIN;
n->objname = $6;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P FUNCTION function_with_argtypes
+ | ALTER EXTENSION name add_drop FUNCTION function_with_argtypes
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_FUNCTION;
n->objname = $6->funcname;
n->objargs = $6->funcargs;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P opt_procedural LANGUAGE name
+ | ALTER EXTENSION name add_drop opt_procedural LANGUAGE name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_LANGUAGE;
n->objname = list_make1(makeString($7));
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P OPERATOR any_operator oper_argtypes
+ | ALTER EXTENSION name add_drop OPERATOR any_operator oper_argtypes
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_OPERATOR;
n->objname = $6;
n->objargs = $7;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P OPERATOR CLASS any_name USING access_method
+ | ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING access_method
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_OPCLASS;
n->objname = $7;
n->objargs = list_make1(makeString($9));
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P OPERATOR FAMILY any_name USING access_method
+ | ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING access_method
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_OPFAMILY;
n->objname = $7;
n->objargs = list_make1(makeString($9));
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P SCHEMA name
+ | ALTER EXTENSION name add_drop SCHEMA name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_SCHEMA;
n->objname = list_make1(makeString($6));
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P TABLE any_name
+ | ALTER EXTENSION name add_drop TABLE any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_TABLE;
n->objname = $6;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P TEXT_P SEARCH PARSER any_name
+ | ALTER EXTENSION name add_drop TEXT_P SEARCH PARSER any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_TSPARSER;
n->objname = $8;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P TEXT_P SEARCH DICTIONARY any_name
+ | ALTER EXTENSION name add_drop TEXT_P SEARCH DICTIONARY any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_TSDICTIONARY;
n->objname = $8;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P TEXT_P SEARCH TEMPLATE any_name
+ | ALTER EXTENSION name add_drop TEXT_P SEARCH TEMPLATE any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_TSTEMPLATE;
n->objname = $8;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P TEXT_P SEARCH CONFIGURATION any_name
+ | ALTER EXTENSION name add_drop TEXT_P SEARCH CONFIGURATION any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_TSCONFIGURATION;
n->objname = $8;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P SEQUENCE any_name
+ | ALTER EXTENSION name add_drop SEQUENCE any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_SEQUENCE;
n->objname = $6;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P VIEW any_name
+ | ALTER EXTENSION name add_drop VIEW any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_VIEW;
n->objname = $6;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P FOREIGN TABLE any_name
+ | ALTER EXTENSION name add_drop FOREIGN TABLE any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_FOREIGN_TABLE;
n->objname = $7;
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P FOREIGN DATA_P WRAPPER name
+ | ALTER EXTENSION name add_drop FOREIGN DATA_P WRAPPER name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_FDW;
n->objname = list_make1(makeString($8));
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P SERVER name
+ | ALTER EXTENSION name add_drop SERVER name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_FOREIGN_SERVER;
n->objname = list_make1(makeString($6));
$$ = (Node *)n;
}
- | ALTER EXTENSION name ADD_P TYPE_P any_name
+ | ALTER EXTENSION name add_drop TYPE_P any_name
{
- AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3;
+ n->action = $4;
n->objtype = OBJECT_TYPE;
n->objname = $6;
$$ = (Node *)n;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 9d1562af7dc..c942de3bf62 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -212,7 +212,7 @@ check_xact_readonly(Node *parsetree)
case T_AlterTSDictionaryStmt:
case T_AlterTSConfigurationStmt:
case T_CreateExtensionStmt:
- case T_AlterExtensionAddStmt:
+ case T_AlterExtensionContentsStmt:
case T_CreateFdwStmt:
case T_AlterFdwStmt:
case T_DropFdwStmt:
@@ -601,8 +601,8 @@ standard_ProcessUtility(Node *parsetree,
CreateExtension((CreateExtensionStmt *) parsetree);
break;
- case T_AlterExtensionAddStmt:
- ExecAlterExtensionAddStmt((AlterExtensionAddStmt *) parsetree);
+ case T_AlterExtensionContentsStmt:
+ ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree);
break;
case T_CreateFdwStmt:
@@ -1680,7 +1680,7 @@ CreateCommandTag(Node *parsetree)
tag = "CREATE EXTENSION";
break;
- case T_AlterExtensionAddStmt:
+ case T_AlterExtensionContentsStmt:
tag = "ALTER EXTENSION";
break;
@@ -2307,7 +2307,7 @@ GetCommandLogLevel(Node *parsetree)
break;
case T_CreateExtensionStmt:
- case T_AlterExtensionAddStmt:
+ case T_AlterExtensionContentsStmt:
lev = LOGSTMT_DDL;
break;
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 1c9623de1e5..c01b02ae3a1 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -855,7 +855,12 @@ psql_completion(char *text, int start, int end)
/* ALTER EXTENSION <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
- COMPLETE_WITH_CONST("SET SCHEMA");
+ {
+ static const char *const list_ALTEREXTENSION[] =
+ {"ADD", "DROP", "SET SCHEMA", NULL};
+
+ COMPLETE_WITH_LIST(list_ALTEREXTENSION);
+ }
/* ALTER FOREIGN */
else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 &&
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 4d7ff8853d1..eda41d69216 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -205,6 +205,9 @@ extern void recordDependencyOnCurrentExtension(const ObjectAddress *object);
extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
bool skipExtensionDeps);
+extern long deleteDependencyRecordsForClass(Oid classId, Oid objectId,
+ Oid refclassId, char deptype);
+
extern long changeDependencyFor(Oid classId, Oid objectId,
Oid refClassId, Oid oldRefObjectId,
Oid newRefObjectId);
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 8c07c3aaeff..7c94449a6cb 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -37,7 +37,7 @@ extern Oid InsertExtensionTuple(const char *extName, Oid extOwner,
Datum extConfig, Datum extCondition,
List *requiredExtensions);
-extern void ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt);
+extern void ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt);
extern Oid get_extension_oid(const char *extname, bool missing_ok);
extern char *get_extension_name(Oid ext_oid);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 1ce97386315..15bf0631e44 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -356,7 +356,7 @@ typedef enum NodeTag
T_SecLabelStmt,
T_CreateForeignTableStmt,
T_CreateExtensionStmt,
- T_AlterExtensionAddStmt,
+ T_AlterExtensionContentsStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 2116c94d0d3..b54f0cfe02f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1546,14 +1546,15 @@ typedef struct CreateExtensionStmt
List *options; /* List of DefElem nodes */
} CreateExtensionStmt;
-typedef struct AlterExtensionAddStmt
+typedef struct AlterExtensionContentsStmt
{
NodeTag type;
char *extname; /* Extension's name */
+ int action; /* +1 = add object, -1 = drop object */
ObjectType objtype; /* Object's type */
List *objname; /* Qualified name of the object */
List *objargs; /* Arguments if needed (eg, for functions) */
-} AlterExtensionAddStmt;
+} AlterExtensionContentsStmt;
/* ----------------------
* Create/Drop FOREIGN DATA WRAPPER Statements