Skip to content

Commit f2fcad2

Browse files
committed
Support ALTER THING .. DEPENDS ON EXTENSION
This introduces a new dependency type which marks an object as depending on an extension, such that if the extension is dropped, the object automatically goes away; and also, if the database is dumped, the object is included in the dump output. Currently the grammar supports this for indexes, triggers, materialized views and functions only, although the utility code is generic so adding support for more object types is a matter of touching the parser rules only. Author: Abhijit Menon-Sen Reviewed-by: Alexander Korotkov, Álvaro Herrera Discussion: http://www.postgresql.org/message-id/20160115062649.GA5068@toroid.org
1 parent 41ea0c2 commit f2fcad2

File tree

23 files changed

+524
-5
lines changed

23 files changed

+524
-5
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,6 +2876,19 @@
28762876
</listitem>
28772877
</varlistentry>
28782878

2879+
<varlistentry>
2880+
<term><symbol>DEPENDENCY_AUTO_EXTENSION</> (<literal>x</>)</term>
2881+
<listitem>
2882+
<para>
2883+
The dependent object is not a member of the extension that is the
2884+
referenced object (and so should not be ignored by pg_dump), but
2885+
cannot function without it and should be dropped when the
2886+
extension itself is. The dependent object may be dropped on its
2887+
own as well.
2888+
</para>
2889+
</listitem>
2890+
</varlistentry>
2891+
28792892
<varlistentry>
28802893
<term><symbol>DEPENDENCY_PIN</> (<literal>p</>)</term>
28812894
<listitem>

doc/src/sgml/ref/alter_function.sgml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="paramet
2929
OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_USER | SESSION_USER }
3030
ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
3131
SET SCHEMA <replaceable>new_schema</replaceable>
32+
ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
33+
DEPENDS ON EXTENSION <replaceable>extension_name</replaceable>
3234

3335
<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
3436

@@ -148,6 +150,15 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="paramet
148150
</listitem>
149151
</varlistentry>
150152

153+
<varlistentry>
154+
<term><replaceable class="parameter">extension_name</replaceable></term>
155+
<listitem>
156+
<para>
157+
The name of the extension that the function is to depend on.
158+
</para>
159+
</listitem>
160+
</varlistentry>
161+
151162
<varlistentry>
152163
<term><literal>CALLED ON NULL INPUT</literal></term>
153164
<term><literal>RETURNS NULL ON NULL INPUT</literal></term>
@@ -299,6 +310,15 @@ ALTER FUNCTION sqrt(integer) SET SCHEMA maths;
299310
</programlisting>
300311
</para>
301312

313+
<para>
314+
To mark the function <literal>sqrt</literal> for type
315+
<type>integer</type> as being dependent on the extension
316+
<literal>mathlib</literal>:
317+
<programlisting>
318+
ALTER FUNCTION sqrt(integer) DEPENDS ON EXTENSION mathlib;
319+
</programlisting>
320+
</para>
321+
302322
<para>
303323
To adjust the search path that is automatically set for a function:
304324
<programlisting>

doc/src/sgml/ref/alter_index.sgml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PostgreSQL documentation
2323
<synopsis>
2424
ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
2525
ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> SET TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable>
26+
ALTER INDEX <replaceable class="PARAMETER">name</replaceable> DEPENDS ON EXTENSION <replaceable class="PARAMETER">extension_name</replaceable>
2627
ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> SET ( <replaceable class="PARAMETER">storage_parameter</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )
2728
ALTER INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> RESET ( <replaceable class="PARAMETER">storage_parameter</replaceable> [, ... ] )
2829
ALTER INDEX ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable> [ OWNED BY <replaceable class="PARAMETER">role_name</replaceable> [, ... ] ]
@@ -82,6 +83,16 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable>
8283
</listitem>
8384
</varlistentry>
8485

86+
<varlistentry>
87+
<term><literal>DEPENDS ON EXTENSION</literal></term>
88+
<listitem>
89+
<para>
90+
This form marks the index as dependent on the extension, such that if the
91+
extension is dropped, the index will automatically be dropped as well.
92+
</para>
93+
</listitem>
94+
</varlistentry>
95+
8596
<varlistentry>
8697
<term><literal>SET ( <replaceable class="PARAMETER">storage_parameter</replaceable> = <replaceable class="PARAMETER">value</replaceable> [, ... ] )</literal></term>
8798
<listitem>
@@ -147,6 +158,15 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable>
147158
</listitem>
148159
</varlistentry>
149160

161+
<varlistentry>
162+
<term><replaceable class="PARAMETER">extension_name</replaceable></term>
163+
<listitem>
164+
<para>
165+
The name of the extension that the index is to depend on.
166+
</para>
167+
</listitem>
168+
</varlistentry>
169+
150170
<varlistentry>
151171
<term><replaceable class="PARAMETER">storage_parameter</replaceable></term>
152172
<listitem>

doc/src/sgml/ref/alter_materialized_view.sgml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ PostgreSQL documentation
2323
<synopsis>
2424
ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
2525
<replaceable class="PARAMETER">action</replaceable> [, ... ]
26+
ALTER MATERIALIZED VIEW <replaceable class="PARAMETER">name</replaceable>
27+
DEPENDS ON EXTENSION <replaceable class="PARAMETER">extension_name</replaceable>
2628
ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
2729
RENAME [ COLUMN ] <replaceable class="PARAMETER">column_name</replaceable> TO <replaceable class="PARAMETER">new_column_name</replaceable>
2830
ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
@@ -67,6 +69,12 @@ ALTER MATERIALIZED VIEW ALL IN TABLESPACE <replaceable class="parameter">name</r
6769
anyway.)
6870
</para>
6971

72+
<para>
73+
The <literal>DEPENDS ON EXTENSION</literal> form marks the materialized view
74+
as dependent on an extension, such that the materialized view will
75+
automatically be dropped if the extension is dropped.
76+
</para>
77+
7078
<para>
7179
The statement subforms and actions available for
7280
<command>ALTER MATERIALIZED VIEW</command> are a subset of those available
@@ -99,6 +107,15 @@ ALTER MATERIALIZED VIEW ALL IN TABLESPACE <replaceable class="parameter">name</r
99107
</listitem>
100108
</varlistentry>
101109

110+
<varlistentry>
111+
<term><replaceable class="PARAMETER">extension_name</replaceable></term>
112+
<listitem>
113+
<para>
114+
The name of the extension that the materialized view is to depend on.
115+
</para>
116+
</listitem>
117+
</varlistentry>
118+
102119
<varlistentry>
103120
<term><replaceable class="PARAMETER">new_column_name</replaceable></term>
104121
<listitem>

doc/src/sgml/ref/alter_trigger.sgml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ PostgreSQL documentation
2222
<refsynopsisdiv>
2323
<synopsis>
2424
ALTER TRIGGER <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
25+
ALTER TRIGGER <replaceable class="PARAMETER">name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> DEPENDS ON EXTENSION <replaceable class="PARAMETER">extension_name</replaceable>
2526
</synopsis>
2627
</refsynopsisdiv>
2728

@@ -32,7 +33,9 @@ ALTER TRIGGER <replaceable class="PARAMETER">name</replaceable> ON <replaceable
3233
<command>ALTER TRIGGER</command> changes properties of an existing
3334
trigger. The <literal>RENAME</literal> clause changes the name of
3435
the given trigger without otherwise changing the trigger
35-
definition.
36+
definition. The <literal>DEPENDS ON EXTENSION</literal> clause marks
37+
the trigger as dependent on an extension, such that if the extension is
38+
dropped, the trigger will automatically be dropped as well.
3639
</para>
3740

3841
<para>
@@ -70,6 +73,15 @@ ALTER TRIGGER <replaceable class="PARAMETER">name</replaceable> ON <replaceable
7073
</para>
7174
</listitem>
7275
</varlistentry>
76+
77+
<varlistentry>
78+
<term><replaceable class="PARAMETER">extension_name</replaceable></term>
79+
<listitem>
80+
<para>
81+
The name of the extension that the trigger is to depend on.
82+
</para>
83+
</listitem>
84+
</varlistentry>
7385
</variablelist>
7486
</refsect1>
7587

@@ -92,6 +104,12 @@ ALTER TRIGGER <replaceable class="PARAMETER">name</replaceable> ON <replaceable
92104
To rename an existing trigger:
93105
<programlisting>
94106
ALTER TRIGGER emp_stamp ON emp RENAME TO emp_track_chgs;
107+
</programlisting></para>
108+
109+
<para>
110+
To mark a trigger as being dependent on an extension:
111+
<programlisting>
112+
ALTER TRIGGER emp_stamp ON emp DEPENDS ON EXTENSION emplib;
95113
</programlisting></para>
96114
</refsect1>
97115

src/backend/catalog/dependency.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ findDependentObjects(const ObjectAddress *object,
589589
{
590590
case DEPENDENCY_NORMAL:
591591
case DEPENDENCY_AUTO:
592+
case DEPENDENCY_AUTO_EXTENSION:
592593
/* no problem */
593594
break;
594595
case DEPENDENCY_INTERNAL:
@@ -788,6 +789,7 @@ findDependentObjects(const ObjectAddress *object,
788789
subflags = DEPFLAG_NORMAL;
789790
break;
790791
case DEPENDENCY_AUTO:
792+
case DEPENDENCY_AUTO_EXTENSION:
791793
subflags = DEPFLAG_AUTO;
792794
break;
793795
case DEPENDENCY_INTERNAL:

src/backend/catalog/objectaddress.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,31 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
10151015
return address;
10161016
}
10171017

1018+
/*
1019+
* Return an ObjectAddress based on a RangeVar and an object name. The
1020+
* name of the relation identified by the RangeVar is prepended to the
1021+
* (possibly empty) list passed in as objname. This is useful to find
1022+
* the ObjectAddress of objects that depend on a relation. All other
1023+
* considerations are exactly as for get_object_address above.
1024+
*/
1025+
ObjectAddress
1026+
get_object_address_rv(ObjectType objtype, RangeVar *rel, List *objname,
1027+
List *objargs, Relation *relp, LOCKMODE lockmode,
1028+
bool missing_ok)
1029+
{
1030+
if (rel)
1031+
{
1032+
objname = lcons(makeString(rel->relname), objname);
1033+
if (rel->schemaname)
1034+
objname = lcons(makeString(rel->schemaname), objname);
1035+
if (rel->catalogname)
1036+
objname = lcons(makeString(rel->catalogname), objname);
1037+
}
1038+
1039+
return get_object_address(objtype, objname, objargs,
1040+
relp, lockmode, missing_ok);
1041+
}
1042+
10181043
/*
10191044
* Find an ObjectAddress for a type of object that is identified by an
10201045
* unqualified name.

src/backend/commands/alter.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,43 @@ ExecRenameStmt(RenameStmt *stmt)
390390
}
391391
}
392392

393+
/*
394+
* Executes an ALTER OBJECT / DEPENDS ON [EXTENSION] statement.
395+
*
396+
* Return value is the address of the altered object. refAddress is an output
397+
* argument which, if not null, receives the address of the object that the
398+
* altered object now depends on.
399+
*/
400+
ObjectAddress
401+
ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddress)
402+
{
403+
ObjectAddress address;
404+
ObjectAddress refAddr;
405+
Relation rel;
406+
407+
address =
408+
get_object_address_rv(stmt->objectType, stmt->relation, stmt->objname,
409+
stmt->objargs, &rel, AccessExclusiveLock, false);
410+
411+
/*
412+
* If a relation was involved, it would have been opened and locked.
413+
* We don't need the relation here, but we'll retain the lock until
414+
* commit.
415+
*/
416+
if (rel)
417+
heap_close(rel, NoLock);
418+
419+
refAddr = get_object_address(OBJECT_EXTENSION, list_make1(stmt->extname),
420+
NULL, &rel, AccessExclusiveLock, false);
421+
Assert(rel == NULL);
422+
if (refAddress)
423+
*refAddress = refAddr;
424+
425+
recordDependencyOn(&address, refAddress, DEPENDENCY_AUTO_EXTENSION);
426+
427+
return address;
428+
}
429+
393430
/*
394431
* Executes an ALTER OBJECT / SET SCHEMA statement. Based on the object
395432
* type, the function appropriate to that type is executed.

src/backend/nodes/copyfuncs.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,20 @@ _copyRenameStmt(const RenameStmt *from)
32043204
return newnode;
32053205
}
32063206

3207+
static AlterObjectDependsStmt *
3208+
_copyAlterObjectDependsStmt(const AlterObjectDependsStmt *from)
3209+
{
3210+
AlterObjectDependsStmt *newnode = makeNode(AlterObjectDependsStmt);
3211+
3212+
COPY_SCALAR_FIELD(objectType);
3213+
COPY_NODE_FIELD(relation);
3214+
COPY_NODE_FIELD(objname);
3215+
COPY_NODE_FIELD(objargs);
3216+
COPY_NODE_FIELD(extname);
3217+
3218+
return newnode;
3219+
}
3220+
32073221
static AlterObjectSchemaStmt *
32083222
_copyAlterObjectSchemaStmt(const AlterObjectSchemaStmt *from)
32093223
{
@@ -4682,6 +4696,9 @@ copyObject(const void *from)
46824696
case T_RenameStmt:
46834697
retval = _copyRenameStmt(from);
46844698
break;
4699+
case T_AlterObjectDependsStmt:
4700+
retval = _copyAlterObjectDependsStmt(from);
4701+
break;
46854702
case T_AlterObjectSchemaStmt:
46864703
retval = _copyAlterObjectSchemaStmt(from);
46874704
break;

src/backend/nodes/equalfuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,18 @@ _equalRenameStmt(const RenameStmt *a, const RenameStmt *b)
13251325
return true;
13261326
}
13271327

1328+
static bool
1329+
_equalAlterObjectDependsStmt(const AlterObjectDependsStmt *a, const AlterObjectDependsStmt *b)
1330+
{
1331+
COMPARE_SCALAR_FIELD(objectType);
1332+
COMPARE_NODE_FIELD(relation);
1333+
COMPARE_NODE_FIELD(objname);
1334+
COMPARE_NODE_FIELD(objargs);
1335+
COMPARE_NODE_FIELD(extname);
1336+
1337+
return true;
1338+
}
1339+
13281340
static bool
13291341
_equalAlterObjectSchemaStmt(const AlterObjectSchemaStmt *a, const AlterObjectSchemaStmt *b)
13301342
{
@@ -3004,6 +3016,9 @@ equal(const void *a, const void *b)
30043016
case T_RenameStmt:
30053017
retval = _equalRenameStmt(a, b);
30063018
break;
3019+
case T_AlterObjectDependsStmt:
3020+
retval = _equalAlterObjectDependsStmt(a, b);
3021+
break;
30073022
case T_AlterObjectSchemaStmt:
30083023
retval = _equalAlterObjectSchemaStmt(a, b);
30093024
break;

0 commit comments

Comments
 (0)