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

Commit 899a04f

Browse files
committed
Avoid duplicates in ALTER ... DEPENDS ON EXTENSION
If the command is attempted for an extension that the object already depends on, silently do nothing. In particular, this means that if a database containing multiple such entries is dumped, the restore will silently do the right thing and record just the first one. (At least, in a world where pg_dump does dump such entries -- which it doesn't currently, but it will.) Backpatch to 9.6, where this kind of dependency was introduced. Reviewed-by: Ibrar Ahmed, Tom Lane (offlist) Discussion: https://postgr.es/m/20200217225333.GA30974@alvherre.pgsql
1 parent 1c91838 commit 899a04f

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

src/backend/catalog/pg_depend.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,49 @@ getExtensionOfObject(Oid classId, Oid objectId)
648648
return result;
649649
}
650650

651+
/*
652+
* Return (possibly NIL) list of extensions that the given object depends on
653+
* in DEPENDENCY_AUTO_EXTENSION mode.
654+
*/
655+
List *
656+
getAutoExtensionsOfObject(Oid classId, Oid objectId)
657+
{
658+
List *result = NIL;
659+
Relation depRel;
660+
ScanKeyData key[2];
661+
SysScanDesc scan;
662+
HeapTuple tup;
663+
664+
depRel = table_open(DependRelationId, AccessShareLock);
665+
666+
ScanKeyInit(&key[0],
667+
Anum_pg_depend_classid,
668+
BTEqualStrategyNumber, F_OIDEQ,
669+
ObjectIdGetDatum(classId));
670+
ScanKeyInit(&key[1],
671+
Anum_pg_depend_objid,
672+
BTEqualStrategyNumber, F_OIDEQ,
673+
ObjectIdGetDatum(objectId));
674+
675+
scan = systable_beginscan(depRel, DependDependerIndexId, true,
676+
NULL, 2, key);
677+
678+
while (HeapTupleIsValid((tup = systable_getnext(scan))))
679+
{
680+
Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
681+
682+
if (depform->refclassid == ExtensionRelationId &&
683+
depform->deptype == DEPENDENCY_AUTO_EXTENSION)
684+
result = lappend_oid(result, depform->refobjid);
685+
}
686+
687+
systable_endscan(scan);
688+
689+
table_close(depRel, AccessShareLock);
690+
691+
return result;
692+
}
693+
651694
/*
652695
* Detect whether a sequence is marked as "owned" by a column
653696
*

src/backend/commands/alter.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre
433433
ObjectAddress address;
434434
ObjectAddress refAddr;
435435
Relation rel;
436+
List *currexts;
436437

437438
address =
438439
get_object_address_rv(stmt->objectType, stmt->relation, (List *) stmt->object,
@@ -462,7 +463,11 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre
462463
if (refAddress)
463464
*refAddress = refAddr;
464465

465-
recordDependencyOn(&address, &refAddr, DEPENDENCY_AUTO_EXTENSION);
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);
466471

467472
return address;
468473
}

src/include/catalog/dependency.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ extern long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
207207
Oid newRefObjectId);
208208

209209
extern Oid getExtensionOfObject(Oid classId, Oid objectId);
210+
extern List *getAutoExtensionsOfObject(Oid classId, Oid objectId);
210211

211212
extern bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId);
212213
extern List *getOwnedSequences(Oid relid);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ SELECT * FROM test_extdep_commands \gexec
4747
CREATE INDEX e ON a (a1)
4848
ALTER INDEX e DEPENDS ON EXTENSION test_ext5
4949
RESET search_path
50+
-- A dependent object made dependent again has no effect
51+
ALTER FUNCTION test_ext.b() DEPENDS ON EXTENSION test_ext5;
5052
-- make sure we have the right dependencies on the extension
5153
SELECT deptype, p.*
5254
FROM pg_depend, pg_identify_object(classid, objid, objsubid) AS p

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ COPY test_extdep_commands FROM stdin;
2727
SELECT * FROM test_extdep_commands;
2828
-- First, test that dependent objects go away when the extension is dropped.
2929
SELECT * FROM test_extdep_commands \gexec
30+
-- A dependent object made dependent again has no effect
31+
ALTER FUNCTION test_ext.b() DEPENDS ON EXTENSION test_ext5;
3032
-- make sure we have the right dependencies on the extension
3133
SELECT deptype, p.*
3234
FROM pg_depend, pg_identify_object(classid, objid, objsubid) AS p

0 commit comments

Comments
 (0)