mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
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.
This commit is contained in:
parent
289d730655
commit
01467d3e4f
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -356,7 +356,7 @@ typedef enum NodeTag
|
||||
T_SecLabelStmt,
|
||||
T_CreateForeignTableStmt,
|
||||
T_CreateExtensionStmt,
|
||||
T_AlterExtensionAddStmt,
|
||||
T_AlterExtensionContentsStmt,
|
||||
|
||||
/*
|
||||
* TAGS FOR PARSE TREE 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
|
||||
|
Loading…
Reference in New Issue
Block a user