Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5fc7039

Browse files
committed
Add ALTER .. NO DEPENDS ON
Commit f2fcad2 (9.6 era) added the ability to mark objects as dependent an extension, but forgot to add a way for such dependencies to be removed. This commit fixes that oversight. Strictly speaking this should be backpatched to 9.6, but due to lack of demand we're not doing so at this time. Discussion: https://postgr.es/m/20200217225333.GA30974@alvherre.pgsql Reviewed-by: ahsan hadi <ahsan.hadi@gmail.com> Reviewed-by: Ibrar Ahmed <ibrar.ahmad@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
1 parent 4157f73 commit 5fc7039

File tree

13 files changed

+168
-36
lines changed

13 files changed

+168
-36
lines changed

doc/src/sgml/ref/alter_function.sgml

+7-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="param
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>
3232
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>
33+
[ NO ] DEPENDS ON EXTENSION <replaceable>extension_name</replaceable>
3434

3535
<phrase>where <replaceable class="parameter">action</replaceable> is one of:</phrase>
3636

@@ -153,10 +153,14 @@ ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="param
153153
</varlistentry>
154154

155155
<varlistentry>
156-
<term><replaceable class="parameter">extension_name</replaceable></term>
156+
<term><literal>DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable></literal></term>
157+
<term><literal>NO DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable></literal></term>
157158
<listitem>
158159
<para>
159-
The name of the extension that the function is to depend on.
160+
This form marks the function as dependent on the extension, or no longer
161+
dependent on that extension if <literal>NO</literal> is specified.
162+
A function that's marked as dependent on an extension is automatically
163+
dropped when the extension is dropped.
160164
</para>
161165
</listitem>
162166
</varlistentry>

doc/src/sgml/ref/alter_index.sgml

+6-3
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,14 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="parameter">name</replaceable>
100100
</varlistentry>
101101

102102
<varlistentry>
103-
<term><literal>DEPENDS ON EXTENSION</literal></term>
103+
<term><literal>DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable></literal></term>
104+
<term><literal>NO DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable></literal></term>
104105
<listitem>
105106
<para>
106-
This form marks the index as dependent on the extension, such that if the
107-
extension is dropped, the index will automatically be dropped as well.
107+
This form marks the index as dependent on the extension, or no longer
108+
dependent on that extension if <literal>NO</literal> is specified.
109+
An index that's marked as dependent on an extension is automatically
110+
dropped when the extension is dropped.
108111
</para>
109112
</listitem>
110113
</varlistentry>

doc/src/sgml/ref/alter_materialized_view.sgml

+4-7
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ ALTER MATERIALIZED VIEW ALL IN TABLESPACE <replaceable class="parameter">name</r
6868
anyway.)
6969
</para>
7070

71-
<para>
72-
The <literal>DEPENDS ON EXTENSION</literal> form marks the materialized view
73-
as dependent on an extension, such that the materialized view will
74-
automatically be dropped if the extension is dropped.
75-
</para>
76-
7771
<para>
7872
The statement subforms and actions available for
7973
<command>ALTER MATERIALIZED VIEW</command> are a subset of those available
@@ -110,7 +104,10 @@ ALTER MATERIALIZED VIEW ALL IN TABLESPACE <replaceable class="parameter">name</r
110104
<term><replaceable class="parameter">extension_name</replaceable></term>
111105
<listitem>
112106
<para>
113-
The name of the extension that the materialized view is to depend on.
107+
The name of the extension that the materialized view is to depend on (or no longer
108+
dependent on, if <literal>NO</literal> is specified). A materialized view
109+
that's marked as dependent on an extension is automatically dropped when
110+
the extension is dropped.
114111
</para>
115112
</listitem>
116113
</varlistentry>

doc/src/sgml/ref/alter_trigger.sgml

+5-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +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>
25+
ALTER TRIGGER <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table_name</replaceable> [ NO ] DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable>
2626
</synopsis>
2727
</refsynopsisdiv>
2828

@@ -78,7 +78,10 @@ ALTER TRIGGER <replaceable class="parameter">name</replaceable> ON <replaceable
7878
<term><replaceable class="parameter">extension_name</replaceable></term>
7979
<listitem>
8080
<para>
81-
The name of the extension that the trigger is to depend on.
81+
The name of the extension that the trigger is to depend on (or no longer
82+
dependent on, if <literal>NO</literal> is specified). A trigger
83+
that's marked as dependent on an extension is automatically dropped when
84+
the extension is dropped.
8285
</para>
8386
</listitem>
8487
</varlistentry>

src/backend/catalog/pg_depend.c

+49
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,55 @@ deleteDependencyRecordsForClass(Oid classId, Oid objectId,
278278
return count;
279279
}
280280

281+
/*
282+
* deleteDependencyRecordsForSpecific -- delete all records with given depender
283+
* classId/objectId, dependee classId/objectId, of the given deptype.
284+
* Returns the number of records deleted.
285+
*/
286+
long
287+
deleteDependencyRecordsForSpecific(Oid classId, Oid objectId, char deptype,
288+
Oid refclassId, Oid refobjectId)
289+
{
290+
long count = 0;
291+
Relation depRel;
292+
ScanKeyData key[2];
293+
SysScanDesc scan;
294+
HeapTuple tup;
295+
296+
depRel = table_open(DependRelationId, RowExclusiveLock);
297+
298+
ScanKeyInit(&key[0],
299+
Anum_pg_depend_classid,
300+
BTEqualStrategyNumber, F_OIDEQ,
301+
ObjectIdGetDatum(classId));
302+
ScanKeyInit(&key[1],
303+
Anum_pg_depend_objid,
304+
BTEqualStrategyNumber, F_OIDEQ,
305+
ObjectIdGetDatum(objectId));
306+
307+
scan = systable_beginscan(depRel, DependDependerIndexId, true,
308+
NULL, 2, key);
309+
310+
while (HeapTupleIsValid(tup = systable_getnext(scan)))
311+
{
312+
Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
313+
314+
if (depform->refclassid == refclassId &&
315+
depform->refobjid == refobjectId &&
316+
depform->deptype == deptype)
317+
{
318+
CatalogTupleDelete(depRel, &tup->t_self);
319+
count++;
320+
}
321+
}
322+
323+
systable_endscan(scan);
324+
325+
table_close(depRel, RowExclusiveLock);
326+
327+
return count;
328+
}
329+
281330
/*
282331
* Adjust dependency record(s) to point to a different object of the same type
283332
*

src/backend/commands/alter.c

+17-7
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ ExecRenameStmt(RenameStmt *stmt)
421421
}
422422

423423
/*
424-
* Executes an ALTER OBJECT / DEPENDS ON [EXTENSION] statement.
424+
* Executes an ALTER OBJECT / [NO] DEPENDS ON EXTENSION statement.
425425
*
426426
* Return value is the address of the altered object. refAddress is an output
427427
* argument which, if not null, receives the address of the object that the
@@ -433,7 +433,6 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre
433433
ObjectAddress address;
434434
ObjectAddress refAddr;
435435
Relation rel;
436-
List *currexts;
437436

438437
address =
439438
get_object_address_rv(stmt->objectType, stmt->relation, (List *) stmt->object,
@@ -463,11 +462,22 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre
463462
if (refAddress)
464463
*refAddress = refAddr;
465464

466-
/* Avoid duplicates */
467-
currexts = getAutoExtensionsOfObject(address.classId,
468-
address.objectId);
469-
if (!list_member_oid(currexts, refAddr.objectId))
470-
recordDependencyOn(&address, &refAddr, DEPENDENCY_AUTO_EXTENSION);
465+
if (stmt->remove)
466+
{
467+
deleteDependencyRecordsForSpecific(address.classId, address.objectId,
468+
DEPENDENCY_AUTO_EXTENSION,
469+
refAddr.classId, refAddr.objectId);
470+
}
471+
else
472+
{
473+
List *currexts;
474+
475+
/* Avoid duplicates */
476+
currexts = getAutoExtensionsOfObject(address.classId,
477+
address.objectId);
478+
if (!list_member_oid(currexts, refAddr.objectId))
479+
recordDependencyOn(&address, &refAddr, DEPENDENCY_AUTO_EXTENSION);
480+
}
471481

472482
return address;
473483
}

src/backend/nodes/copyfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -3638,6 +3638,7 @@ _copyAlterObjectDependsStmt(const AlterObjectDependsStmt *from)
36383638
COPY_NODE_FIELD(relation);
36393639
COPY_NODE_FIELD(object);
36403640
COPY_NODE_FIELD(extname);
3641+
COPY_SCALAR_FIELD(remove);
36413642

36423643
return newnode;
36433644
}

src/backend/nodes/equalfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ _equalAlterObjectDependsStmt(const AlterObjectDependsStmt *a, const AlterObjectD
14491449
COMPARE_NODE_FIELD(relation);
14501450
COMPARE_NODE_FIELD(object);
14511451
COMPARE_NODE_FIELD(extname);
1452+
COMPARE_SCALAR_FIELD(remove);
14521453

14531454
return true;
14541455
}

src/backend/parser/gram.y

+23-13
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
320320
%type <list> vac_analyze_option_list
321321
%type <node> vac_analyze_option_arg
322322
%type <defelt> drop_option
323-
%type <boolean> opt_or_replace
323+
%type <boolean> opt_or_replace opt_no
324324
opt_grant_grant_option opt_grant_admin_option
325325
opt_nowait opt_if_exists opt_with_data
326326
opt_transaction_chain
@@ -9053,57 +9053,67 @@ opt_set_data: SET DATA_P { $$ = 1; }
90539053
*****************************************************************************/
90549054

90559055
AlterObjectDependsStmt:
9056-
ALTER FUNCTION function_with_argtypes DEPENDS ON EXTENSION name
9056+
ALTER FUNCTION function_with_argtypes opt_no DEPENDS ON EXTENSION name
90579057
{
90589058
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
90599059
n->objectType = OBJECT_FUNCTION;
90609060
n->object = (Node *) $3;
9061-
n->extname = makeString($7);
9061+
n->extname = makeString($8);
9062+
n->remove = $4;
90629063
$$ = (Node *)n;
90639064
}
9064-
| ALTER PROCEDURE function_with_argtypes DEPENDS ON EXTENSION name
9065+
| ALTER PROCEDURE function_with_argtypes opt_no DEPENDS ON EXTENSION name
90659066
{
90669067
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
90679068
n->objectType = OBJECT_PROCEDURE;
90689069
n->object = (Node *) $3;
9069-
n->extname = makeString($7);
9070+
n->extname = makeString($8);
9071+
n->remove = $4;
90709072
$$ = (Node *)n;
90719073
}
9072-
| ALTER ROUTINE function_with_argtypes DEPENDS ON EXTENSION name
9074+
| ALTER ROUTINE function_with_argtypes opt_no DEPENDS ON EXTENSION name
90739075
{
90749076
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
90759077
n->objectType = OBJECT_ROUTINE;
90769078
n->object = (Node *) $3;
9077-
n->extname = makeString($7);
9079+
n->extname = makeString($8);
9080+
n->remove = $4;
90789081
$$ = (Node *)n;
90799082
}
9080-
| ALTER TRIGGER name ON qualified_name DEPENDS ON EXTENSION name
9083+
| ALTER TRIGGER name ON qualified_name opt_no DEPENDS ON EXTENSION name
90819084
{
90829085
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
90839086
n->objectType = OBJECT_TRIGGER;
90849087
n->relation = $5;
90859088
n->object = (Node *) list_make1(makeString($3));
9086-
n->extname = makeString($9);
9089+
n->extname = makeString($10);
9090+
n->remove = $6;
90879091
$$ = (Node *)n;
90889092
}
9089-
| ALTER MATERIALIZED VIEW qualified_name DEPENDS ON EXTENSION name
9093+
| ALTER MATERIALIZED VIEW qualified_name opt_no DEPENDS ON EXTENSION name
90909094
{
90919095
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
90929096
n->objectType = OBJECT_MATVIEW;
90939097
n->relation = $4;
9094-
n->extname = makeString($8);
9098+
n->extname = makeString($9);
9099+
n->remove = $5;
90959100
$$ = (Node *)n;
90969101
}
9097-
| ALTER INDEX qualified_name DEPENDS ON EXTENSION name
9102+
| ALTER INDEX qualified_name opt_no DEPENDS ON EXTENSION name
90989103
{
90999104
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
91009105
n->objectType = OBJECT_INDEX;
91019106
n->relation = $3;
9102-
n->extname = makeString($7);
9107+
n->extname = makeString($8);
9108+
n->remove = $4;
91039109
$$ = (Node *)n;
91049110
}
91059111
;
91069112

9113+
opt_no: NO { $$ = true; }
9114+
| /* EMPTY */ { $$ = false; }
9115+
;
9116+
91079117
/*****************************************************************************
91089118
*
91099119
* ALTER THING name SET SCHEMA name

src/include/catalog/dependency.h

+4
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
196196
extern long deleteDependencyRecordsForClass(Oid classId, Oid objectId,
197197
Oid refclassId, char deptype);
198198

199+
extern long deleteDependencyRecordsForSpecific(Oid classId, Oid objectId,
200+
char deptype,
201+
Oid refclassId, Oid refobjectId);
202+
199203
extern long changeDependencyFor(Oid classId, Oid objectId,
200204
Oid refClassId, Oid oldRefObjectId,
201205
Oid newRefObjectId);

src/include/nodes/parsenodes.h

+1
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,7 @@ typedef struct AlterObjectDependsStmt
29362936
RangeVar *relation; /* in case a table is involved */
29372937
Node *object; /* name of the object */
29382938
Value *extname; /* extension name */
2939+
bool remove; /* set true to remove dep rather than add */
29392940
} AlterObjectDependsStmt;
29402941

29412942
/* ----------------------

src/test/modules/test_extensions/expected/test_extdepend.out

+34
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,39 @@ SELECT deptype, i.*
150150
(0 rows)
151151

152152
DROP TABLE a;
153+
RESET search_path;
153154
DROP SCHEMA test_ext CASCADE;
154155
NOTICE: drop cascades to extension test_ext5
156+
-- Fourth test: we can mark the objects as dependent, then unmark; then the
157+
-- drop of the extension does nothing
158+
SELECT * FROM test_extdep_commands \gexec
159+
CREATE SCHEMA test_ext
160+
CREATE EXTENSION test_ext5 SCHEMA test_ext
161+
SET search_path TO test_ext
162+
CREATE TABLE a (a1 int)
163+
164+
CREATE FUNCTION b() RETURNS TRIGGER LANGUAGE plpgsql AS
165+
$$ BEGIN NEW.a1 := NEW.a1 + 42; RETURN NEW; END; $$
166+
ALTER FUNCTION b() DEPENDS ON EXTENSION test_ext5
167+
168+
CREATE TRIGGER c BEFORE INSERT ON a FOR EACH ROW EXECUTE PROCEDURE b()
169+
ALTER TRIGGER c ON a DEPENDS ON EXTENSION test_ext5
170+
171+
CREATE MATERIALIZED VIEW d AS SELECT * FROM a
172+
ALTER MATERIALIZED VIEW d DEPENDS ON EXTENSION test_ext5
173+
174+
CREATE INDEX e ON a (a1)
175+
ALTER INDEX e DEPENDS ON EXTENSION test_ext5
176+
RESET search_path
177+
SET search_path TO test_ext;
178+
ALTER FUNCTION b() NO DEPENDS ON EXTENSION test_ext5;
179+
ALTER TRIGGER c ON a NO DEPENDS ON EXTENSION test_ext5;
180+
ALTER MATERIALIZED VIEW d NO DEPENDS ON EXTENSION test_ext5;
181+
ALTER INDEX e NO DEPENDS ON EXTENSION test_ext5;
182+
DROP EXTENSION test_ext5;
183+
DROP TRIGGER c ON a;
184+
DROP FUNCTION b();
185+
DROP MATERIALIZED VIEW d;
186+
DROP INDEX e;
187+
DROP SCHEMA test_ext CASCADE;
188+
NOTICE: drop cascades to table a

src/test/modules/test_extensions/sql/test_extdepend.sql

+16-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ SELECT deptype, i.*
7070
refobjid=(SELECT oid FROM pg_extension WHERE extname='test_ext5'))
7171
OR (refclassid='pg_class'::regclass AND refobjid='test_ext.a'::regclass)
7272
AND NOT deptype IN ('i', 'a');
73-
7473
DROP TABLE a;
74+
RESET search_path;
75+
DROP SCHEMA test_ext CASCADE;
76+
77+
-- Fourth test: we can mark the objects as dependent, then unmark; then the
78+
-- drop of the extension does nothing
79+
SELECT * FROM test_extdep_commands \gexec
80+
SET search_path TO test_ext;
81+
ALTER FUNCTION b() NO DEPENDS ON EXTENSION test_ext5;
82+
ALTER TRIGGER c ON a NO DEPENDS ON EXTENSION test_ext5;
83+
ALTER MATERIALIZED VIEW d NO DEPENDS ON EXTENSION test_ext5;
84+
ALTER INDEX e NO DEPENDS ON EXTENSION test_ext5;
85+
DROP EXTENSION test_ext5;
86+
DROP TRIGGER c ON a;
87+
DROP FUNCTION b();
88+
DROP MATERIALIZED VIEW d;
89+
DROP INDEX e;
7590
DROP SCHEMA test_ext CASCADE;

0 commit comments

Comments
 (0)