1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Implement "ALTER EXTENSION ADD object".

This is an essential component of making the extension feature usable;
first because it's needed in the process of converting an existing
installation containing "loose" objects of an old contrib module into
the extension-based world, and second because we'll have to use it
in pg_dump --binary-upgrade, as per recent discussion.

Loosely based on part of Dimitri Fontaine's ALTER EXTENSION UPGRADE
patch.
This commit is contained in:
Tom Lane
2011-02-09 11:55:32 -05:00
parent 70802e0dbe
commit 5bc178b89f
10 changed files with 600 additions and 254 deletions

View File

@ -1134,7 +1134,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
if (getExtensionOfObject(RelationRelationId, tableoid) !=
CurrentExtensionObject)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("table \"%s\" is not a member of the extension being created",
tablename)));
@ -1392,3 +1392,60 @@ AlterExtensionNamespace(List *names, const char *newschema)
changeDependencyFor(ExtensionRelationId, extensionOid,
NamespaceRelationId, oldNspOid, nspOid);
}
/*
* Execute ALTER EXTENSION ADD
*/
void
ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt)
{
ObjectAddress extension;
ObjectAddress object;
Relation relation;
/*
* For now, insist on superuser privilege. Later we might want to
* relax this to ownership of the target object and the extension.
*/
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use ALTER EXTENSION"))));
/* Do this next to fail on nonexistent extension */
extension.classId = ExtensionRelationId;
extension.objectId = get_extension_oid(stmt->extname, false);
extension.objectSubId = 0;
/*
* 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 = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
&relation, ShareUpdateExclusiveLock);
/*
* Complain if object is already attached to some extension.
*/
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))));
/*
* OK, add the dependency.
*/
recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
/*
* If get_object_address() opened the relation for us, we close it to keep
* the reference count correct - but we retain any locks acquired by
* get_object_address() until commit time, to guard against concurrent
* activity.
*/
if (relation != NULL)
relation_close(relation, NoLock);
}

View File

@ -3250,6 +3250,19 @@ _copyCreateExtensionStmt(CreateExtensionStmt *from)
return newnode;
}
static AlterExtensionAddStmt *
_copyAlterExtensionAddStmt(AlterExtensionAddStmt *from)
{
AlterExtensionAddStmt *newnode = makeNode(AlterExtensionAddStmt);
COPY_STRING_FIELD(extname);
COPY_SCALAR_FIELD(objtype);
COPY_NODE_FIELD(objname);
COPY_NODE_FIELD(objargs);
return newnode;
}
static CreateFdwStmt *
_copyCreateFdwStmt(CreateFdwStmt *from)
{
@ -4252,6 +4265,9 @@ copyObject(void *from)
case T_CreateExtensionStmt:
retval = _copyCreateExtensionStmt(from);
break;
case T_AlterExtensionAddStmt:
retval = _copyAlterExtensionAddStmt(from);
break;
case T_CreateFdwStmt:
retval = _copyCreateFdwStmt(from);
break;

View File

@ -1654,6 +1654,17 @@ _equalCreateExtensionStmt(CreateExtensionStmt *a, CreateExtensionStmt *b)
return true;
}
static bool
_equalAlterExtensionAddStmt(AlterExtensionAddStmt *a, AlterExtensionAddStmt *b)
{
COMPARE_STRING_FIELD(extname);
COMPARE_SCALAR_FIELD(objtype);
COMPARE_NODE_FIELD(objname);
COMPARE_NODE_FIELD(objargs);
return true;
}
static bool
_equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b)
{
@ -2857,6 +2868,9 @@ equal(void *a, void *b)
case T_CreateExtensionStmt:
retval = _equalCreateExtensionStmt(a, b);
break;
case T_AlterExtensionAddStmt:
retval = _equalAlterExtensionAddStmt(a, b);
break;
case T_CreateFdwStmt:
retval = _equalCreateFdwStmt(a, b);
break;

View File

@ -185,7 +185,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterForeignTableStmt
AlterExtensionAddStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
AlterDefaultPrivilegesStmt DefACLAction
@ -664,6 +664,7 @@ stmt :
| AlterDefaultPrivilegesStmt
| AlterDomainStmt
| AlterEnumStmt
| AlterExtensionAddStmt
| AlterFdwStmt
| AlterForeignServerStmt
| AlterForeignTableStmt
@ -3248,6 +3249,189 @@ create_extension_opt_item:
}
;
/*****************************************************************************
*
* ALTER EXTENSION name ADD object-identifier
*
*****************************************************************************/
AlterExtensionAddStmt:
ALTER EXTENSION name ADD_P AGGREGATE func_name aggr_args
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_AGGREGATE;
n->objname = $6;
n->objargs = $7;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P CAST '(' Typename AS Typename ')'
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
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
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_CONVERSION;
n->objname = $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P DOMAIN_P any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_DOMAIN;
n->objname = $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P FUNCTION function_with_argtypes
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_FUNCTION;
n->objname = $6->funcname;
n->objargs = $6->funcargs;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P opt_procedural LANGUAGE name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_LANGUAGE;
n->objname = list_make1(makeString($7));
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P OPERATOR any_operator oper_argtypes
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_OPERATOR;
n->objname = $6;
n->objargs = $7;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P OPERATOR CLASS any_name USING access_method
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
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
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_OPFAMILY;
n->objname = $7;
n->objargs = list_make1(makeString($9));
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P SCHEMA name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_SCHEMA;
n->objname = list_make1(makeString($6));
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P TABLE any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_TABLE;
n->objname = $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P TEXT_P SEARCH PARSER any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_TSPARSER;
n->objname = $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P TEXT_P SEARCH DICTIONARY any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_TSDICTIONARY;
n->objname = $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P TEXT_P SEARCH TEMPLATE any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_TSTEMPLATE;
n->objname = $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P TEXT_P SEARCH CONFIGURATION any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_TSCONFIGURATION;
n->objname = $8;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P SEQUENCE any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_SEQUENCE;
n->objname = $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P VIEW any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_VIEW;
n->objname = $6;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P FOREIGN TABLE any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_FOREIGN_TABLE;
n->objname = $7;
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P FOREIGN DATA_P WRAPPER name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_FDW;
n->objname = list_make1(makeString($8));
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P SERVER name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_FOREIGN_SERVER;
n->objname = list_make1(makeString($6));
$$ = (Node *)n;
}
| ALTER EXTENSION name ADD_P TYPE_P any_name
{
AlterExtensionAddStmt *n = makeNode(AlterExtensionAddStmt);
n->extname = $3;
n->objtype = OBJECT_TYPE;
n->objname = $6;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* QUERY:

View File

@ -212,6 +212,7 @@ check_xact_readonly(Node *parsetree)
case T_AlterTSDictionaryStmt:
case T_AlterTSConfigurationStmt:
case T_CreateExtensionStmt:
case T_AlterExtensionAddStmt:
case T_CreateFdwStmt:
case T_AlterFdwStmt:
case T_DropFdwStmt:
@ -600,6 +601,10 @@ standard_ProcessUtility(Node *parsetree,
CreateExtension((CreateExtensionStmt *) parsetree);
break;
case T_AlterExtensionAddStmt:
ExecAlterExtensionAddStmt((AlterExtensionAddStmt *) parsetree);
break;
case T_CreateFdwStmt:
CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
break;
@ -1421,6 +1426,123 @@ QueryReturnsTuples(Query *parsetree)
#endif
/*
* AlterObjectTypeCommandTag
* helper function for CreateCommandTag
*
* This covers most cases where ALTER is used with an ObjectType enum.
*/
static const char *
AlterObjectTypeCommandTag(ObjectType objtype)
{
const char *tag;
switch (objtype)
{
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
case OBJECT_ATTRIBUTE:
tag = "ALTER TYPE";
break;
case OBJECT_CAST:
tag = "ALTER CAST";
break;
case OBJECT_COLUMN:
tag = "ALTER TABLE";
break;
case OBJECT_CONSTRAINT:
tag = "ALTER TABLE";
break;
case OBJECT_CONVERSION:
tag = "ALTER CONVERSION";
break;
case OBJECT_DATABASE:
tag = "ALTER DATABASE";
break;
case OBJECT_DOMAIN:
tag = "ALTER DOMAIN";
break;
case OBJECT_EXTENSION:
tag = "ALTER EXTENSION";
break;
case OBJECT_FDW:
tag = "ALTER FOREIGN DATA WRAPPER";
break;
case OBJECT_FOREIGN_SERVER:
tag = "ALTER SERVER";
break;
case OBJECT_FOREIGN_TABLE:
tag = "ALTER FOREIGN TABLE";
break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
case OBJECT_INDEX:
tag = "ALTER INDEX";
break;
case OBJECT_LANGUAGE:
tag = "ALTER LANGUAGE";
break;
case OBJECT_LARGEOBJECT:
tag = "ALTER LARGE OBJECT";
break;
case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS";
break;
case OBJECT_OPERATOR:
tag = "ALTER OPERATOR";
break;
case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY";
break;
case OBJECT_ROLE:
tag = "ALTER ROLE";
break;
case OBJECT_RULE:
tag = "ALTER RULE";
break;
case OBJECT_SCHEMA:
tag = "ALTER SCHEMA";
break;
case OBJECT_SEQUENCE:
tag = "ALTER SEQUENCE";
break;
case OBJECT_TABLE:
tag = "ALTER TABLE";
break;
case OBJECT_TABLESPACE:
tag = "ALTER TABLESPACE";
break;
case OBJECT_TRIGGER:
tag = "ALTER TRIGGER";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSPARSER:
tag = "ALTER TEXT SEARCH PARSER";
break;
case OBJECT_TSTEMPLATE:
tag = "ALTER TEXT SEARCH TEMPLATE";
break;
case OBJECT_TYPE:
tag = "ALTER TYPE";
break;
case OBJECT_VIEW:
tag = "ALTER VIEW";
break;
default:
tag = "???";
break;
}
return tag;
}
/*
* CreateCommandTag
* utility to get a string representation of the command operation,
@ -1558,6 +1680,10 @@ CreateCommandTag(Node *parsetree)
tag = "CREATE EXTENSION";
break;
case T_AlterExtensionAddStmt:
tag = "ALTER EXTENSION";
break;
case T_CreateFdwStmt:
tag = "CREATE FOREIGN DATA WRAPPER";
break;
@ -1665,235 +1791,19 @@ CreateCommandTag(Node *parsetree)
break;
case T_RenameStmt:
switch (((RenameStmt *) parsetree)->renameType)
{
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
case OBJECT_CONVERSION:
tag = "ALTER CONVERSION";
break;
case OBJECT_DATABASE:
tag = "ALTER DATABASE";
break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
case OBJECT_INDEX:
tag = "ALTER INDEX";
break;
case OBJECT_LANGUAGE:
tag = "ALTER LANGUAGE";
break;
case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS";
break;
case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY";
break;
case OBJECT_ROLE:
tag = "ALTER ROLE";
break;
case OBJECT_SCHEMA:
tag = "ALTER SCHEMA";
break;
case OBJECT_SEQUENCE:
tag = "ALTER SEQUENCE";
break;
case OBJECT_COLUMN:
{
RenameStmt *stmt = (RenameStmt *) parsetree;
if (stmt->relationType == OBJECT_FOREIGN_TABLE)
tag = "ALTER FOREIGN TABLE";
else
tag = "ALTER TABLE";
}
break;
case OBJECT_TABLE:
tag = "ALTER TABLE";
break;
case OBJECT_TABLESPACE:
tag = "ALTER TABLESPACE";
break;
case OBJECT_TRIGGER:
tag = "ALTER TRIGGER";
break;
case OBJECT_VIEW:
tag = "ALTER VIEW";
break;
case OBJECT_FOREIGN_TABLE:
tag = "ALTER FOREIGN TABLE";
break;
case OBJECT_TSPARSER:
tag = "ALTER TEXT SEARCH PARSER";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSTEMPLATE:
tag = "ALTER TEXT SEARCH TEMPLATE";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
case OBJECT_ATTRIBUTE:
case OBJECT_TYPE:
tag = "ALTER TYPE";
break;
default:
tag = "???";
break;
}
tag = AlterObjectTypeCommandTag(((RenameStmt *) parsetree)->renameType);
break;
case T_AlterObjectSchemaStmt:
switch (((AlterObjectSchemaStmt *) parsetree)->objectType)
{
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
case OBJECT_CONVERSION:
tag = "ALTER CONVERSION";
break;
case OBJECT_DOMAIN:
tag = "ALTER DOMAIN";
break;
case OBJECT_EXTENSION:
tag = "ALTER EXTENSION";
break;
case OBJECT_OPERATOR:
tag = "ALTER OPERATOR";
break;
case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS";
break;
case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY";
break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
case OBJECT_SEQUENCE:
tag = "ALTER SEQUENCE";
break;
case OBJECT_TABLE:
tag = "ALTER TABLE";
break;
case OBJECT_TYPE:
tag = "ALTER TYPE";
break;
case OBJECT_TSPARSER:
tag = "ALTER TEXT SEARCH PARSER";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSTEMPLATE:
tag = "ALTER TEXT SEARCH TEMPLATE";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
case OBJECT_VIEW:
tag = "ALTER VIEW";
break;
case OBJECT_FOREIGN_TABLE:
tag = "ALTER FOREIGN TABLE";
break;
default:
tag = "???";
break;
}
tag = AlterObjectTypeCommandTag(((AlterObjectSchemaStmt *) parsetree)->objectType);
break;
case T_AlterOwnerStmt:
switch (((AlterOwnerStmt *) parsetree)->objectType)
{
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
case OBJECT_CONVERSION:
tag = "ALTER CONVERSION";
break;
case OBJECT_DATABASE:
tag = "ALTER DATABASE";
break;
case OBJECT_DOMAIN:
tag = "ALTER DOMAIN";
break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
case OBJECT_LANGUAGE:
tag = "ALTER LANGUAGE";
break;
case OBJECT_LARGEOBJECT:
tag = "ALTER LARGE OBJECT";
break;
case OBJECT_OPERATOR:
tag = "ALTER OPERATOR";
break;
case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS";
break;
case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY";
break;
case OBJECT_SCHEMA:
tag = "ALTER SCHEMA";
break;
case OBJECT_TABLESPACE:
tag = "ALTER TABLESPACE";
break;
case OBJECT_TYPE:
tag = "ALTER TYPE";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_FDW:
tag = "ALTER FOREIGN DATA WRAPPER";
break;
case OBJECT_FOREIGN_SERVER:
tag = "ALTER SERVER";
break;
case OBJECT_FOREIGN_TABLE:
tag = "ALTER FOREIGN TABLE";
break;
default:
tag = "???";
break;
}
tag = AlterObjectTypeCommandTag(((AlterOwnerStmt *) parsetree)->objectType);
break;
case T_AlterTableStmt:
switch (((AlterTableStmt *) parsetree)->relkind)
{
case OBJECT_TABLE:
tag = "ALTER TABLE";
break;
case OBJECT_INDEX:
tag = "ALTER INDEX";
break;
case OBJECT_SEQUENCE:
tag = "ALTER SEQUENCE";
break;
case OBJECT_TYPE:
tag = "ALTER TYPE";
break;
case OBJECT_VIEW:
tag = "ALTER VIEW";
break;
case OBJECT_FOREIGN_TABLE:
tag = "ALTER FOREIGN TABLE";
break;
default:
tag = "???";
break;
}
tag = AlterObjectTypeCommandTag(((AlterTableStmt *) parsetree)->relkind);
break;
case T_AlterDomainStmt:
@ -2391,18 +2301,13 @@ GetCommandLogLevel(Node *parsetree)
break;
case T_CreateTableSpaceStmt:
lev = LOGSTMT_DDL;
break;
case T_DropTableSpaceStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterTableSpaceOptionsStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateExtensionStmt:
case T_AlterExtensionAddStmt:
lev = LOGSTMT_DDL;
break;

View File

@ -32,6 +32,8 @@ extern void CreateExtension(CreateExtensionStmt *stmt);
extern void RemoveExtensions(DropStmt *stmt);
extern void RemoveExtensionById(Oid extId);
extern void ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt);
extern Oid get_extension_oid(const char *extname, bool missing_ok);
extern char *get_extension_name(Oid ext_oid);

View File

@ -356,6 +356,7 @@ typedef enum NodeTag
T_SecLabelStmt,
T_CreateForeignTableStmt,
T_CreateExtensionStmt,
T_AlterExtensionAddStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)

View File

@ -1060,13 +1060,13 @@ typedef struct SetOperationStmt
/*
* When a command can act on several kinds of objects with only one
* parse structure required, use these constants to designate the
* object type.
* object type. Note that commands typically don't support all the types.
*/
typedef enum ObjectType
{
OBJECT_AGGREGATE,
OBJECT_ATTRIBUTE, /* type's attribute, when distinct from column */
OBJECT_ATTRIBUTE, /* type's attribute, when distinct from column */
OBJECT_CAST,
OBJECT_COLUMN,
OBJECT_CONSTRAINT,
@ -1535,7 +1535,7 @@ typedef struct AlterTableSpaceOptionsStmt
} AlterTableSpaceOptionsStmt;
/* ----------------------
* Create Extension Statement
* Create/Alter Extension Statements
* ----------------------
*/
@ -1546,6 +1546,15 @@ typedef struct CreateExtensionStmt
List *options; /* List of DefElem nodes */
} CreateExtensionStmt;
typedef struct AlterExtensionAddStmt
{
NodeTag type;
char *extname; /* Extension's name */
ObjectType objtype; /* Object's type */
List *objname; /* Qualified name of the object */
List *objargs; /* Arguments if needed (eg, for functions) */
} AlterExtensionAddStmt;
/* ----------------------
* Create/Drop FOREIGN DATA WRAPPER Statements
* ----------------------