Commit 01467d3e authored by Tom Lane's avatar Tom Lane

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.
parent 289d7306
...@@ -25,6 +25,7 @@ PostgreSQL documentation ...@@ -25,6 +25,7 @@ PostgreSQL documentation
<synopsis> <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> 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> 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> <phrase>where <replaceable class="PARAMETER">member_object</replaceable> is:</phrase>
...@@ -82,6 +83,17 @@ ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD ...@@ -82,6 +83,17 @@ ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD
</para> </para>
</listitem> </listitem>
</varlistentry> </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> </variablelist>
See <xref linkend="extend-extensions"> for more information about these See <xref linkend="extend-extensions"> for more information about these
...@@ -123,7 +135,8 @@ ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD ...@@ -123,7 +135,8 @@ ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD
<term><replaceable class="parameter">operator_name</replaceable></term> <term><replaceable class="parameter">operator_name</replaceable></term>
<listitem> <listitem>
<para> <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, aggregates, domains, foreign tables, functions, operators,
operator classes, operator families, sequences, text search objects, operator classes, operator families, sequences, text search objects,
types, and views can be schema-qualified. types, and views can be schema-qualified.
......
...@@ -199,6 +199,57 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId, ...@@ -199,6 +199,57 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId,
return count; 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 * 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) ...@@ -470,39 +521,8 @@ sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
void void
markSequenceUnowned(Oid seqId) markSequenceUnowned(Oid seqId)
{ {
Relation depRel; deleteDependencyRecordsForClass(RelationRelationId, seqId,
ScanKeyData key[2]; RelationRelationId, DEPENDENCY_AUTO);
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);
} }
/* /*
......
...@@ -1436,14 +1436,15 @@ AlterExtensionNamespace(List *names, const char *newschema) ...@@ -1436,14 +1436,15 @@ AlterExtensionNamespace(List *names, const char *newschema)
} }
/* /*
* Execute ALTER EXTENSION ADD * Execute ALTER EXTENSION ADD/DROP
*/ */
void void
ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt) ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
{ {
ObjectAddress extension; ObjectAddress extension;
ObjectAddress object; ObjectAddress object;
Relation relation; Relation relation;
Oid oldExtension;
/* /*
* For now, insist on superuser privilege. Later we might want to * For now, insist on superuser privilege. Later we might want to
...@@ -1462,25 +1463,54 @@ ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt) ...@@ -1462,25 +1463,54 @@ ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt)
/* /*
* Translate the parser representation that identifies the object into * Translate the parser representation that identifies the object into
* an ObjectAddress. get_object_address() will throw an error if the * an ObjectAddress. get_object_address() will throw an error if the
* object does not exist, and will also acquire a lock on the object * object does not exist, and will also acquire a lock on the object to
* to guard against concurrent DROP and ALTER EXTENSION ADD operations. * guard against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
*/ */
object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs, object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
&relation, ShareUpdateExclusiveLock); &relation, ShareUpdateExclusiveLock);
/* /*
* Complain if object is already attached to some extension. * Check existing extension membership.
*/ */
if (getExtensionOfObject(object.classId, object.objectId) != InvalidOid) oldExtension = getExtensionOfObject(object.classId, object.objectId);
if (stmt->action > 0)
{
/*
* ADD, so complain if object is already attached to some extension.
*/
if (OidIsValid(oldExtension))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("%s is already a member of an extension", errmsg("%s is already a member of extension \"%s\"",
getObjectDescription(&object)))); getObjectDescription(&object),
get_extension_name(oldExtension))));
/* /*
* OK, add the dependency. * OK, add the dependency.
*/ */
recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION); 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 * If get_object_address() opened the relation for us, we close it to keep
......
...@@ -3251,12 +3251,13 @@ _copyCreateExtensionStmt(CreateExtensionStmt *from) ...@@ -3251,12 +3251,13 @@ _copyCreateExtensionStmt(CreateExtensionStmt *from)
return newnode; return newnode;
} }
static AlterExtensionAddStmt * static AlterExtensionContentsStmt *
_copyAlterExtensionAddStmt(AlterExtensionAddStmt *from) _copyAlterExtensionContentsStmt(AlterExtensionContentsStmt *from)
{ {
AlterExtensionAddStmt *newnode = makeNode(AlterExtensionAddStmt); AlterExtensionContentsStmt *newnode = makeNode(AlterExtensionContentsStmt);
COPY_STRING_FIELD(extname); COPY_STRING_FIELD(extname);
COPY_SCALAR_FIELD(action);
COPY_SCALAR_FIELD(objtype); COPY_SCALAR_FIELD(objtype);
COPY_NODE_FIELD(objname); COPY_NODE_FIELD(objname);
COPY_NODE_FIELD(objargs); COPY_NODE_FIELD(objargs);
...@@ -4266,8 +4267,8 @@ copyObject(void *from) ...@@ -4266,8 +4267,8 @@ copyObject(void *from)
case T_CreateExtensionStmt: case T_CreateExtensionStmt:
retval = _copyCreateExtensionStmt(from); retval = _copyCreateExtensionStmt(from);
break; break;
case T_AlterExtensionAddStmt: case T_AlterExtensionContentsStmt:
retval = _copyAlterExtensionAddStmt(from); retval = _copyAlterExtensionContentsStmt(from);
break; break;
case T_CreateFdwStmt: case T_CreateFdwStmt:
retval = _copyCreateFdwStmt(from); retval = _copyCreateFdwStmt(from);
......
...@@ -1655,9 +1655,10 @@ _equalCreateExtensionStmt(CreateExtensionStmt *a, CreateExtensionStmt *b) ...@@ -1655,9 +1655,10 @@ _equalCreateExtensionStmt(CreateExtensionStmt *a, CreateExtensionStmt *b)
} }
static bool static bool
_equalAlterExtensionAddStmt(AlterExtensionAddStmt *a, AlterExtensionAddStmt *b) _equalAlterExtensionContentsStmt(AlterExtensionContentsStmt *a, AlterExtensionContentsStmt *b)
{ {
COMPARE_STRING_FIELD(extname); COMPARE_STRING_FIELD(extname);
COMPARE_SCALAR_FIELD(action);
COMPARE_SCALAR_FIELD(objtype); COMPARE_SCALAR_FIELD(objtype);
COMPARE_NODE_FIELD(objname); COMPARE_NODE_FIELD(objname);
COMPARE_NODE_FIELD(objargs); COMPARE_NODE_FIELD(objargs);
...@@ -2868,8 +2869,8 @@ equal(void *a, void *b) ...@@ -2868,8 +2869,8 @@ equal(void *a, void *b)
case T_CreateExtensionStmt: case T_CreateExtensionStmt:
retval = _equalCreateExtensionStmt(a, b); retval = _equalCreateExtensionStmt(a, b);
break; break;
case T_AlterExtensionAddStmt: case T_AlterExtensionContentsStmt:
retval = _equalAlterExtensionAddStmt(a, b); retval = _equalAlterExtensionContentsStmt(a, b);
break; break;
case T_CreateFdwStmt: case T_CreateFdwStmt:
retval = _equalCreateFdwStmt(a, b); retval = _equalCreateFdwStmt(a, b);
......
...@@ -185,7 +185,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_ ...@@ -185,7 +185,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterExtensionAddStmt AlterForeignTableStmt AlterExtensionContentsStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt AlterRoleStmt AlterRoleSetStmt
AlterDefaultPrivilegesStmt DefACLAction AlterDefaultPrivilegesStmt DefACLAction
...@@ -664,7 +664,7 @@ stmt : ...@@ -664,7 +664,7 @@ stmt :
| AlterDefaultPrivilegesStmt | AlterDefaultPrivilegesStmt
| AlterDomainStmt | AlterDomainStmt
| AlterEnumStmt | AlterEnumStmt
| AlterExtensionAddStmt | AlterExtensionContentsStmt
| AlterFdwStmt | AlterFdwStmt
| AlterForeignServerStmt | AlterForeignServerStmt
| AlterForeignTableStmt | AlterForeignTableStmt
...@@ -3251,181 +3251,202 @@ create_extension_opt_item: ...@@ -3251,181 +3251,202 @@ create_extension_opt_item:
/***************************************************************************** /*****************************************************************************
* *
* ALTER EXTENSION name ADD object-identifier * ALTER EXTENSION name ADD/DROP object-identifier
* *
*****************************************************************************/ *****************************************************************************/
AlterExtensionAddStmt: AlterExtensionContentsStmt:
ALTER EXTENSION name ADD_P AGGREGATE func_name aggr_args ALTER EXTENSION name add_drop AGGREGATE func_name aggr_args
{ {
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt); AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
n->extname = $3; n->extname = $3;
n->action = $4;
n->objtype = OBJECT_AGGREGATE; n->objtype = OBJECT_AGGREGATE;
n->objname = $6; n->objname = $6;
n->objargs = $7; n->objargs = $7;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_CAST; n->objtype = OBJECT_CAST;
n->objname = list_make1($7); n->objname = list_make1($7);
n->objargs = list_make1($9); n->objargs = list_make1($9);
$$ = (Node *) n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_CONVERSION; n->objtype = OBJECT_CONVERSION;
n->objname = $6; n->objname = $6;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_DOMAIN; n->objtype = OBJECT_DOMAIN;
n->objname = $6; n->objname = $6;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_FUNCTION; n->objtype = OBJECT_FUNCTION;
n->objname = $6->funcname; n->objname = $6->funcname;
n->objargs = $6->funcargs; n->objargs = $6->funcargs;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_LANGUAGE; n->objtype = OBJECT_LANGUAGE;
n->objname = list_make1(makeString($7)); n->objname = list_make1(makeString($7));
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_OPERATOR; n->objtype = OBJECT_OPERATOR;
n->objname = $6; n->objname = $6;
n->objargs = $7; n->objargs = $7;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_OPCLASS; n->objtype = OBJECT_OPCLASS;
n->objname = $7; n->objname = $7;
n->objargs = list_make1(makeString($9)); n->objargs = list_make1(makeString($9));
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_OPFAMILY; n->objtype = OBJECT_OPFAMILY;
n->objname = $7; n->objname = $7;
n->objargs = list_make1(makeString($9)); n->objargs = list_make1(makeString($9));
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_SCHEMA; n->objtype = OBJECT_SCHEMA;
n->objname = list_make1(makeString($6)); n->objname = list_make1(makeString($6));
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_TABLE; n->objtype = OBJECT_TABLE;
n->objname = $6; n->objname = $6;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSPARSER; n->objtype = OBJECT_TSPARSER;
n->objname = $8; n->objname = $8;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSDICTIONARY; n->objtype = OBJECT_TSDICTIONARY;
n->objname = $8; n->objname = $8;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSTEMPLATE; n->objtype = OBJECT_TSTEMPLATE;
n->objname = $8; n->objname = $8;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_TSCONFIGURATION; n->objtype = OBJECT_TSCONFIGURATION;
n->objname = $8; n->objname = $8;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_SEQUENCE; n->objtype = OBJECT_SEQUENCE;
n->objname = $6; n->objname = $6;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_VIEW; n->objtype = OBJECT_VIEW;
n->objname = $6; n->objname = $6;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_FOREIGN_TABLE; n->objtype = OBJECT_FOREIGN_TABLE;
n->objname = $7; n->objname = $7;
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_FDW; n->objtype = OBJECT_FDW;
n->objname = list_make1(makeString($8)); n->objname = list_make1(makeString($8));
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_FOREIGN_SERVER; n->objtype = OBJECT_FOREIGN_SERVER;
n->objname = list_make1(makeString($6)); n->objname = list_make1(makeString($6));
$$ = (Node *)n; $$ = (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->extname = $3;
n->action = $4;
n->objtype = OBJECT_TYPE; n->objtype = OBJECT_TYPE;
n->objname = $6; n->objname = $6;
$$ = (Node *)n; $$ = (Node *)n;
......
...@@ -212,7 +212,7 @@ check_xact_readonly(Node *parsetree) ...@@ -212,7 +212,7 @@ check_xact_readonly(Node *parsetree)
case T_AlterTSDictionaryStmt: case T_AlterTSDictionaryStmt:
case T_AlterTSConfigurationStmt: case T_AlterTSConfigurationStmt:
case T_CreateExtensionStmt: case T_CreateExtensionStmt:
case T_AlterExtensionAddStmt: case T_AlterExtensionContentsStmt:
case T_CreateFdwStmt: case T_CreateFdwStmt:
case T_AlterFdwStmt: case T_AlterFdwStmt:
case T_DropFdwStmt: case T_DropFdwStmt:
...@@ -601,8 +601,8 @@ standard_ProcessUtility(Node *parsetree, ...@@ -601,8 +601,8 @@ standard_ProcessUtility(Node *parsetree,
CreateExtension((CreateExtensionStmt *) parsetree); CreateExtension((CreateExtensionStmt *) parsetree);
break; break;
case T_AlterExtensionAddStmt: case T_AlterExtensionContentsStmt:
ExecAlterExtensionAddStmt((AlterExtensionAddStmt *) parsetree); ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree);
break; break;
case T_CreateFdwStmt: case T_CreateFdwStmt:
...@@ -1680,7 +1680,7 @@ CreateCommandTag(Node *parsetree) ...@@ -1680,7 +1680,7 @@ CreateCommandTag(Node *parsetree)
tag = "CREATE EXTENSION"; tag = "CREATE EXTENSION";
break; break;
case T_AlterExtensionAddStmt: case T_AlterExtensionContentsStmt:
tag = "ALTER EXTENSION"; tag = "ALTER EXTENSION";
break; break;
...@@ -2307,7 +2307,7 @@ GetCommandLogLevel(Node *parsetree) ...@@ -2307,7 +2307,7 @@ GetCommandLogLevel(Node *parsetree)
break; break;
case T_CreateExtensionStmt: case T_CreateExtensionStmt:
case T_AlterExtensionAddStmt: case T_AlterExtensionContentsStmt:
lev = LOGSTMT_DDL; lev = LOGSTMT_DDL;
break; break;
......
...@@ -855,7 +855,12 @@ psql_completion(char *text, int start, int end) ...@@ -855,7 +855,12 @@ psql_completion(char *text, int start, int end)
/* ALTER EXTENSION <name> */ /* ALTER EXTENSION <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "EXTENSION") == 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 */ /* ALTER FOREIGN */
else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 &&
......
...@@ -205,6 +205,9 @@ extern void recordDependencyOnCurrentExtension(const ObjectAddress *object); ...@@ -205,6 +205,9 @@ extern void recordDependencyOnCurrentExtension(const ObjectAddress *object);
extern long deleteDependencyRecordsFor(Oid classId, Oid objectId, extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
bool skipExtensionDeps); bool skipExtensionDeps);
extern long deleteDependencyRecordsForClass(Oid classId, Oid objectId,
Oid refclassId, char deptype);
extern long changeDependencyFor(Oid classId, Oid objectId, extern long changeDependencyFor(Oid classId, Oid objectId,
Oid refClassId, Oid oldRefObjectId, Oid refClassId, Oid oldRefObjectId,
Oid newRefObjectId); Oid newRefObjectId);
......
...@@ -37,7 +37,7 @@ extern Oid InsertExtensionTuple(const char *extName, Oid extOwner, ...@@ -37,7 +37,7 @@ extern Oid InsertExtensionTuple(const char *extName, Oid extOwner,
Datum extConfig, Datum extCondition, Datum extConfig, Datum extCondition,
List *requiredExtensions); List *requiredExtensions);
extern void ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt); extern void ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt);
extern Oid get_extension_oid(const char *extname, bool missing_ok); extern Oid get_extension_oid(const char *extname, bool missing_ok);
extern char *get_extension_name(Oid ext_oid); extern char *get_extension_name(Oid ext_oid);
......
...@@ -356,7 +356,7 @@ typedef enum NodeTag ...@@ -356,7 +356,7 @@ typedef enum NodeTag
T_SecLabelStmt, T_SecLabelStmt,
T_CreateForeignTableStmt, T_CreateForeignTableStmt,
T_CreateExtensionStmt, T_CreateExtensionStmt,
T_AlterExtensionAddStmt, T_AlterExtensionContentsStmt,
/* /*
* TAGS FOR PARSE TREE NODES (parsenodes.h) * TAGS FOR PARSE TREE NODES (parsenodes.h)
......
...@@ -1546,14 +1546,15 @@ typedef struct CreateExtensionStmt ...@@ -1546,14 +1546,15 @@ typedef struct CreateExtensionStmt
List *options; /* List of DefElem nodes */ List *options; /* List of DefElem nodes */
} CreateExtensionStmt; } CreateExtensionStmt;
typedef struct AlterExtensionAddStmt typedef struct AlterExtensionContentsStmt
{ {
NodeTag type; NodeTag type;
char *extname; /* Extension's name */ char *extname; /* Extension's name */
int action; /* +1 = add object, -1 = drop object */
ObjectType objtype; /* Object's type */ ObjectType objtype; /* Object's type */
List *objname; /* Qualified name of the object */ List *objname; /* Qualified name of the object */
List *objargs; /* Arguments if needed (eg, for functions) */ List *objargs; /* Arguments if needed (eg, for functions) */
} AlterExtensionAddStmt; } AlterExtensionContentsStmt;
/* ---------------------- /* ----------------------
* Create/Drop FOREIGN DATA WRAPPER Statements * Create/Drop FOREIGN DATA WRAPPER Statements
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment