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

@ -331,6 +331,18 @@
data; see below.)
</para>
<para>
The kinds of SQL objects that can be members of an extension are shown in
the description of <xref linkend="sql-alterextension">. Notably, objects
that are database-cluster-wide, such as databases, roles, and tablespaces,
cannot be extension members since an extension is only known within one
database. (Although an extension script is not prohibited from creating
such objects, if it does so they will not be tracked as part of the
extension.) Also notice that while a table can be a member of an
extension, its subsidiary objects such as indexes are not directly
considered members of the extension.
</para>
<sect2>
<title>Extension Files</title>

View File

@ -23,7 +23,32 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
ALTER EXTENSION <replaceable class="PARAMETER">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>
<phrase>where <replaceable class="PARAMETER">member_object</replaceable> is:</phrase>
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable> [, ...] ) |
CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) |
CONVERSION <replaceable class="PARAMETER">object_name</replaceable> |
DOMAIN <replaceable class="PARAMETER">object_name</replaceable> |
FOREIGN DATA WRAPPER <replaceable class="PARAMETER">object_name</replaceable> |
FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> |
FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) |
OPERATOR <replaceable class="PARAMETER">operator_name</replaceable> (<replaceable class="PARAMETER">left_type</replaceable>, <replaceable class="PARAMETER">right_type</replaceable>) |
OPERATOR CLASS <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> |
OPERATOR FAMILY <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> |
[ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">object_name</replaceable> |
SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
SERVER <replaceable class="PARAMETER">object_name</replaceable> |
TABLE <replaceable class="PARAMETER">object_name</replaceable> |
TEXT SEARCH CONFIGURATION <replaceable class="PARAMETER">object_name</replaceable> |
TEXT SEARCH DICTIONARY <replaceable class="PARAMETER">object_name</replaceable> |
TEXT SEARCH PARSER <replaceable class="PARAMETER">object_name</replaceable> |
TEXT SEARCH TEMPLATE <replaceable class="PARAMETER">object_name</replaceable> |
TYPE <replaceable class="PARAMETER">object_name</replaceable> |
VIEW <replaceable class="PARAMETER">object_name</replaceable>
</synopsis>
</refsynopsisdiv>
@ -31,8 +56,8 @@ ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <re
<title>Description</title>
<para>
<command>ALTER EXTENSION</command> changes the definition of an existing extension.
Currently there is only one subform:
<command>ALTER EXTENSION</command> changes the definition of an installed
extension. There are several subforms:
<variablelist>
<varlistentry>
@ -41,37 +66,151 @@ ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <re
<para>
This form moves the extension's objects into another schema. The
extension has to be <firstterm>relocatable</> for this command to
succeed. See <xref linkend="extend-extensions"> for details.
succeed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>ADD <replaceable class="PARAMETER">member_object</replaceable></literal></term>
<listitem>
<para>
This form adds an existing object to the extension. This is mainly
useful in extension upgrade scripts. The object will subsequently
be treated as a member of the extension; notably, it can only be
dropped by dropping the extension.
</para>
</listitem>
</varlistentry>
</variablelist>
See <xref linkend="extend-extensions"> for more information about these
operations.
</para>
<para>
Only superusers can execute <command>ALTER EXTENSION</command>.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<para>
<variablelist>
<varlistentry>
<term><replaceable class="PARAMETER">name</replaceable></term>
<listitem>
<para>
The name of an installed extension.
</para>
</listitem>
</varlistentry>
<para>
<variablelist>
<varlistentry>
<term><replaceable class="PARAMETER">extension_name</replaceable></term>
<listitem>
<para>
The name of an installed extension.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">new_schema</replaceable></term>
<listitem>
<para>
The new schema for the extension.
</para>
</listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><replaceable class="PARAMETER">new_schema</replaceable></term>
<listitem>
<para>
The new schema for the extension.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">object_name</replaceable></term>
<term><replaceable class="parameter">agg_name</replaceable></term>
<term><replaceable class="parameter">function_name</replaceable></term>
<term><replaceable class="parameter">operator_name</replaceable></term>
<listitem>
<para>
The name of an object to be added to 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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">agg_type</replaceable></term>
<listitem>
<para>
An input data type on which the aggregate function operates.
To reference a zero-argument aggregate function, write <literal>*</>
in place of the list of input data types.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>source_type</replaceable></term>
<listitem>
<para>
The name of the source data type of the cast.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>target_type</replaceable></term>
<listitem>
<para>
The name of the target data type of the cast.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">argmode</replaceable></term>
<listitem>
<para>
The mode of a function argument: <literal>IN</>, <literal>OUT</>,
<literal>INOUT</>, or <literal>VARIADIC</>.
If omitted, the default is <literal>IN</>.
Note that <command>ALTER EXTENSION</command> does not actually pay
any attention to <literal>OUT</> arguments, since only the input
arguments are needed to determine the function's identity.
So it is sufficient to list the <literal>IN</>, <literal>INOUT</>,
and <literal>VARIADIC</> arguments.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">argname</replaceable></term>
<listitem>
<para>
The name of a function argument.
Note that <command>ALTER EXTENSION</command> does not actually pay
any attention to argument names, since only the argument data
types are needed to determine the function's identity.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">argtype</replaceable></term>
<listitem>
<para>
The data type(s) of the function's arguments (optionally
schema-qualified), if any.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>PROCEDURAL</literal></term>
<listitem>
<para>
This is a noise word.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>
@ -83,6 +222,13 @@ ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <re
to <literal>utils</literal>:
<programlisting>
ALTER EXTENSION hstore SET SCHEMA utils;
</programlisting>
</para>
<para>
To add an existing function to the <literal>hstore</literal> extension:
<programlisting>
ALTER EXTENSION hstore ADD FUNCTION populate_record(anyelement, hstore);
</programlisting>
</para>
</refsect1>

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
* ----------------------