Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5bc178b

Browse files
committed
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.
1 parent 70802e0 commit 5bc178b

File tree

10 files changed

+601
-255
lines changed

10 files changed

+601
-255
lines changed

doc/src/sgml/extend.sgml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,18 @@
331331
data; see below.)
332332
</para>
333333

334+
<para>
335+
The kinds of SQL objects that can be members of an extension are shown in
336+
the description of <xref linkend="sql-alterextension">. Notably, objects
337+
that are database-cluster-wide, such as databases, roles, and tablespaces,
338+
cannot be extension members since an extension is only known within one
339+
database. (Although an extension script is not prohibited from creating
340+
such objects, if it does so they will not be tracked as part of the
341+
extension.) Also notice that while a table can be a member of an
342+
extension, its subsidiary objects such as indexes are not directly
343+
considered members of the extension.
344+
</para>
345+
334346
<sect2>
335347
<title>Extension Files</title>
336348

doc/src/sgml/ref/alter_extension.sgml

Lines changed: 170 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,41 @@ PostgreSQL documentation
2323

2424
<refsynopsisdiv>
2525
<synopsis>
26-
ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
26+
ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
27+
ALTER EXTENSION <replaceable class="PARAMETER">extension_name</replaceable> ADD <replaceable class="PARAMETER">member_object</replaceable>
28+
29+
<phrase>where <replaceable class="PARAMETER">member_object</replaceable> is:</phrase>
30+
31+
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable> [, ...] ) |
32+
CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) |
33+
CONVERSION <replaceable class="PARAMETER">object_name</replaceable> |
34+
DOMAIN <replaceable class="PARAMETER">object_name</replaceable> |
35+
FOREIGN DATA WRAPPER <replaceable class="PARAMETER">object_name</replaceable> |
36+
FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> |
37+
FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) |
38+
OPERATOR <replaceable class="PARAMETER">operator_name</replaceable> (<replaceable class="PARAMETER">left_type</replaceable>, <replaceable class="PARAMETER">right_type</replaceable>) |
39+
OPERATOR CLASS <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> |
40+
OPERATOR FAMILY <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> |
41+
[ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">object_name</replaceable> |
42+
SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
43+
SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
44+
SERVER <replaceable class="PARAMETER">object_name</replaceable> |
45+
TABLE <replaceable class="PARAMETER">object_name</replaceable> |
46+
TEXT SEARCH CONFIGURATION <replaceable class="PARAMETER">object_name</replaceable> |
47+
TEXT SEARCH DICTIONARY <replaceable class="PARAMETER">object_name</replaceable> |
48+
TEXT SEARCH PARSER <replaceable class="PARAMETER">object_name</replaceable> |
49+
TEXT SEARCH TEMPLATE <replaceable class="PARAMETER">object_name</replaceable> |
50+
TYPE <replaceable class="PARAMETER">object_name</replaceable> |
51+
VIEW <replaceable class="PARAMETER">object_name</replaceable>
2752
</synopsis>
2853
</refsynopsisdiv>
2954

3055
<refsect1>
3156
<title>Description</title>
3257

3358
<para>
34-
<command>ALTER EXTENSION</command> changes the definition of an existing extension.
35-
Currently there is only one subform:
59+
<command>ALTER EXTENSION</command> changes the definition of an installed
60+
extension. There are several subforms:
3661

3762
<variablelist>
3863
<varlistentry>
@@ -41,37 +66,151 @@ ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <re
4166
<para>
4267
This form moves the extension's objects into another schema. The
4368
extension has to be <firstterm>relocatable</> for this command to
44-
succeed. See <xref linkend="extend-extensions"> for details.
69+
succeed.
70+
</para>
71+
</listitem>
72+
</varlistentry>
73+
74+
<varlistentry>
75+
<term><literal>ADD <replaceable class="PARAMETER">member_object</replaceable></literal></term>
76+
<listitem>
77+
<para>
78+
This form adds an existing object to the extension. This is mainly
79+
useful in extension upgrade scripts. The object will subsequently
80+
be treated as a member of the extension; notably, it can only be
81+
dropped by dropping the extension.
4582
</para>
4683
</listitem>
4784
</varlistentry>
4885
</variablelist>
86+
87+
See <xref linkend="extend-extensions"> for more information about these
88+
operations.
89+
</para>
90+
91+
<para>
92+
Only superusers can execute <command>ALTER EXTENSION</command>.
4993
</para>
5094
</refsect1>
5195

5296
<refsect1>
5397
<title>Parameters</title>
5498

55-
<para>
56-
<variablelist>
57-
<varlistentry>
58-
<term><replaceable class="PARAMETER">name</replaceable></term>
59-
<listitem>
60-
<para>
61-
The name of an installed extension.
62-
</para>
63-
</listitem>
64-
</varlistentry>
65-
66-
<varlistentry>
67-
<term><replaceable class="PARAMETER">new_schema</replaceable></term>
68-
<listitem>
69-
<para>
70-
The new schema for the extension.
71-
</para>
72-
</listitem>
73-
</varlistentry>
74-
</variablelist>
99+
<para>
100+
<variablelist>
101+
<varlistentry>
102+
<term><replaceable class="PARAMETER">extension_name</replaceable></term>
103+
<listitem>
104+
<para>
105+
The name of an installed extension.
106+
</para>
107+
</listitem>
108+
</varlistentry>
109+
110+
<varlistentry>
111+
<term><replaceable class="PARAMETER">new_schema</replaceable></term>
112+
<listitem>
113+
<para>
114+
The new schema for the extension.
115+
</para>
116+
</listitem>
117+
</varlistentry>
118+
119+
<varlistentry>
120+
<term><replaceable class="parameter">object_name</replaceable></term>
121+
<term><replaceable class="parameter">agg_name</replaceable></term>
122+
<term><replaceable class="parameter">function_name</replaceable></term>
123+
<term><replaceable class="parameter">operator_name</replaceable></term>
124+
<listitem>
125+
<para>
126+
The name of an object to be added to the extension. Names of tables,
127+
aggregates, domains, foreign tables, functions, operators,
128+
operator classes, operator families, sequences, text search objects,
129+
types, and views can be schema-qualified.
130+
</para>
131+
</listitem>
132+
</varlistentry>
133+
134+
<varlistentry>
135+
<term><replaceable class="parameter">agg_type</replaceable></term>
136+
<listitem>
137+
<para>
138+
An input data type on which the aggregate function operates.
139+
To reference a zero-argument aggregate function, write <literal>*</>
140+
in place of the list of input data types.
141+
</para>
142+
</listitem>
143+
</varlistentry>
144+
145+
<varlistentry>
146+
<term><replaceable>source_type</replaceable></term>
147+
<listitem>
148+
<para>
149+
The name of the source data type of the cast.
150+
</para>
151+
</listitem>
152+
</varlistentry>
153+
154+
<varlistentry>
155+
<term><replaceable>target_type</replaceable></term>
156+
<listitem>
157+
<para>
158+
The name of the target data type of the cast.
159+
</para>
160+
</listitem>
161+
</varlistentry>
162+
163+
<varlistentry>
164+
<term><replaceable class="parameter">argmode</replaceable></term>
165+
166+
<listitem>
167+
<para>
168+
The mode of a function argument: <literal>IN</>, <literal>OUT</>,
169+
<literal>INOUT</>, or <literal>VARIADIC</>.
170+
If omitted, the default is <literal>IN</>.
171+
Note that <command>ALTER EXTENSION</command> does not actually pay
172+
any attention to <literal>OUT</> arguments, since only the input
173+
arguments are needed to determine the function's identity.
174+
So it is sufficient to list the <literal>IN</>, <literal>INOUT</>,
175+
and <literal>VARIADIC</> arguments.
176+
</para>
177+
</listitem>
178+
</varlistentry>
179+
180+
<varlistentry>
181+
<term><replaceable class="parameter">argname</replaceable></term>
182+
183+
<listitem>
184+
<para>
185+
The name of a function argument.
186+
Note that <command>ALTER EXTENSION</command> does not actually pay
187+
any attention to argument names, since only the argument data
188+
types are needed to determine the function's identity.
189+
</para>
190+
</listitem>
191+
</varlistentry>
192+
193+
<varlistentry>
194+
<term><replaceable class="parameter">argtype</replaceable></term>
195+
196+
<listitem>
197+
<para>
198+
The data type(s) of the function's arguments (optionally
199+
schema-qualified), if any.
200+
</para>
201+
</listitem>
202+
</varlistentry>
203+
204+
<varlistentry>
205+
<term><literal>PROCEDURAL</literal></term>
206+
207+
<listitem>
208+
<para>
209+
This is a noise word.
210+
</para>
211+
</listitem>
212+
</varlistentry>
213+
</variablelist>
75214
</para>
76215
</refsect1>
77216

@@ -83,6 +222,13 @@ ALTER EXTENSION <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <re
83222
to <literal>utils</literal>:
84223
<programlisting>
85224
ALTER EXTENSION hstore SET SCHEMA utils;
225+
</programlisting>
226+
</para>
227+
228+
<para>
229+
To add an existing function to the <literal>hstore</literal> extension:
230+
<programlisting>
231+
ALTER EXTENSION hstore ADD FUNCTION populate_record(anyelement, hstore);
86232
</programlisting>
87233
</para>
88234
</refsect1>

src/backend/commands/extension.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
11341134
if (getExtensionOfObject(RelationRelationId, tableoid) !=
11351135
CurrentExtensionObject)
11361136
ereport(ERROR,
1137-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1137+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11381138
errmsg("table \"%s\" is not a member of the extension being created",
11391139
tablename)));
11401140

@@ -1392,3 +1392,60 @@ AlterExtensionNamespace(List *names, const char *newschema)
13921392
changeDependencyFor(ExtensionRelationId, extensionOid,
13931393
NamespaceRelationId, oldNspOid, nspOid);
13941394
}
1395+
1396+
/*
1397+
* Execute ALTER EXTENSION ADD
1398+
*/
1399+
void
1400+
ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt)
1401+
{
1402+
ObjectAddress extension;
1403+
ObjectAddress object;
1404+
Relation relation;
1405+
1406+
/*
1407+
* For now, insist on superuser privilege. Later we might want to
1408+
* relax this to ownership of the target object and the extension.
1409+
*/
1410+
if (!superuser())
1411+
ereport(ERROR,
1412+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1413+
(errmsg("must be superuser to use ALTER EXTENSION"))));
1414+
1415+
/* Do this next to fail on nonexistent extension */
1416+
extension.classId = ExtensionRelationId;
1417+
extension.objectId = get_extension_oid(stmt->extname, false);
1418+
extension.objectSubId = 0;
1419+
1420+
/*
1421+
* Translate the parser representation that identifies the object into
1422+
* an ObjectAddress. get_object_address() will throw an error if the
1423+
* object does not exist, and will also acquire a lock on the object
1424+
* to guard against concurrent DROP and ALTER EXTENSION ADD operations.
1425+
*/
1426+
object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
1427+
&relation, ShareUpdateExclusiveLock);
1428+
1429+
/*
1430+
* Complain if object is already attached to some extension.
1431+
*/
1432+
if (getExtensionOfObject(object.classId, object.objectId) != InvalidOid)
1433+
ereport(ERROR,
1434+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1435+
errmsg("%s is already a member of an extension",
1436+
getObjectDescription(&object))));
1437+
1438+
/*
1439+
* OK, add the dependency.
1440+
*/
1441+
recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
1442+
1443+
/*
1444+
* If get_object_address() opened the relation for us, we close it to keep
1445+
* the reference count correct - but we retain any locks acquired by
1446+
* get_object_address() until commit time, to guard against concurrent
1447+
* activity.
1448+
*/
1449+
if (relation != NULL)
1450+
relation_close(relation, NoLock);
1451+
}

src/backend/nodes/copyfuncs.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3250,6 +3250,19 @@ _copyCreateExtensionStmt(CreateExtensionStmt *from)
32503250
return newnode;
32513251
}
32523252

3253+
static AlterExtensionAddStmt *
3254+
_copyAlterExtensionAddStmt(AlterExtensionAddStmt *from)
3255+
{
3256+
AlterExtensionAddStmt *newnode = makeNode(AlterExtensionAddStmt);
3257+
3258+
COPY_STRING_FIELD(extname);
3259+
COPY_SCALAR_FIELD(objtype);
3260+
COPY_NODE_FIELD(objname);
3261+
COPY_NODE_FIELD(objargs);
3262+
3263+
return newnode;
3264+
}
3265+
32533266
static CreateFdwStmt *
32543267
_copyCreateFdwStmt(CreateFdwStmt *from)
32553268
{
@@ -4252,6 +4265,9 @@ copyObject(void *from)
42524265
case T_CreateExtensionStmt:
42534266
retval = _copyCreateExtensionStmt(from);
42544267
break;
4268+
case T_AlterExtensionAddStmt:
4269+
retval = _copyAlterExtensionAddStmt(from);
4270+
break;
42554271
case T_CreateFdwStmt:
42564272
retval = _copyCreateFdwStmt(from);
42574273
break;

src/backend/nodes/equalfuncs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,17 @@ _equalCreateExtensionStmt(CreateExtensionStmt *a, CreateExtensionStmt *b)
16541654
return true;
16551655
}
16561656

1657+
static bool
1658+
_equalAlterExtensionAddStmt(AlterExtensionAddStmt *a, AlterExtensionAddStmt *b)
1659+
{
1660+
COMPARE_STRING_FIELD(extname);
1661+
COMPARE_SCALAR_FIELD(objtype);
1662+
COMPARE_NODE_FIELD(objname);
1663+
COMPARE_NODE_FIELD(objargs);
1664+
1665+
return true;
1666+
}
1667+
16571668
static bool
16581669
_equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b)
16591670
{
@@ -2857,6 +2868,9 @@ equal(void *a, void *b)
28572868
case T_CreateExtensionStmt:
28582869
retval = _equalCreateExtensionStmt(a, b);
28592870
break;
2871+
case T_AlterExtensionAddStmt:
2872+
retval = _equalAlterExtensionAddStmt(a, b);
2873+
break;
28602874
case T_CreateFdwStmt:
28612875
retval = _equalCreateFdwStmt(a, b);
28622876
break;

0 commit comments

Comments
 (0)