From 01467d3e4f51fe304c0160c9895484ad696d1e87 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Thu, 10 Feb 2011 17:36:44 -0500 Subject: [PATCH] Extend "ALTER EXTENSION ADD object" to permit "DROP object" as well. Per discussion, this is something we should have sooner rather than later, and it doesn't take much additional code to support it. --- doc/src/sgml/ref/alter_extension.sgml | 15 +++- src/backend/catalog/pg_depend.c | 86 ++++++++++++-------- src/backend/commands/extension.c | 58 +++++++++---- src/backend/nodes/copyfuncs.c | 11 +-- src/backend/nodes/equalfuncs.c | 7 +- src/backend/parser/gram.y | 113 +++++++++++++++----------- src/backend/tcop/utility.c | 10 +-- src/bin/psql/tab-complete.c | 7 +- src/include/catalog/dependency.h | 3 + src/include/commands/extension.h | 2 +- src/include/nodes/nodes.h | 2 +- src/include/nodes/parsenodes.h | 5 +- 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 @@ -199,6 +199,57 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId, return count; } +/* + * 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 * @@ -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 -- GitLab