00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/genam.h"
00018 #include "access/heapam.h"
00019 #include "access/htup_details.h"
00020 #include "access/xact.h"
00021 #include "catalog/catalog.h"
00022 #include "catalog/dependency.h"
00023 #include "catalog/indexing.h"
00024 #include "catalog/pg_authid.h"
00025 #include "catalog/pg_collation.h"
00026 #include "catalog/pg_conversion.h"
00027 #include "catalog/pg_database.h"
00028 #include "catalog/pg_default_acl.h"
00029 #include "catalog/pg_event_trigger.h"
00030 #include "catalog/pg_extension.h"
00031 #include "catalog/pg_foreign_data_wrapper.h"
00032 #include "catalog/pg_foreign_server.h"
00033 #include "catalog/pg_language.h"
00034 #include "catalog/pg_largeobject.h"
00035 #include "catalog/pg_largeobject_metadata.h"
00036 #include "catalog/pg_namespace.h"
00037 #include "catalog/pg_operator.h"
00038 #include "catalog/pg_opclass.h"
00039 #include "catalog/pg_opfamily.h"
00040 #include "catalog/pg_proc.h"
00041 #include "catalog/pg_shdepend.h"
00042 #include "catalog/pg_tablespace.h"
00043 #include "catalog/pg_type.h"
00044 #include "commands/alter.h"
00045 #include "commands/dbcommands.h"
00046 #include "commands/collationcmds.h"
00047 #include "commands/conversioncmds.h"
00048 #include "commands/defrem.h"
00049 #include "commands/event_trigger.h"
00050 #include "commands/extension.h"
00051 #include "commands/proclang.h"
00052 #include "commands/schemacmds.h"
00053 #include "commands/tablecmds.h"
00054 #include "commands/typecmds.h"
00055 #include "storage/lmgr.h"
00056 #include "miscadmin.h"
00057 #include "utils/acl.h"
00058 #include "utils/fmgroids.h"
00059 #include "utils/syscache.h"
00060 #include "utils/tqual.h"
00061
00062
00063 typedef enum
00064 {
00065 LOCAL_OBJECT,
00066 SHARED_OBJECT,
00067 REMOTE_OBJECT
00068 } objectType;
00069
00070 static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2);
00071 static Oid classIdGetDbId(Oid classId);
00072 static void shdepChangeDep(Relation sdepRel,
00073 Oid classid, Oid objid, int32 objsubid,
00074 Oid refclassid, Oid refobjid,
00075 SharedDependencyType deptype);
00076 static void shdepAddDependency(Relation sdepRel,
00077 Oid classId, Oid objectId, int32 objsubId,
00078 Oid refclassId, Oid refobjId,
00079 SharedDependencyType deptype);
00080 static void shdepDropDependency(Relation sdepRel,
00081 Oid classId, Oid objectId, int32 objsubId,
00082 bool drop_subobjects,
00083 Oid refclassId, Oid refobjId,
00084 SharedDependencyType deptype);
00085 static void storeObjectDescription(StringInfo descs, objectType type,
00086 ObjectAddress *object,
00087 SharedDependencyType deptype,
00088 int count);
00089 static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel);
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 void
00106 recordSharedDependencyOn(ObjectAddress *depender,
00107 ObjectAddress *referenced,
00108 SharedDependencyType deptype)
00109 {
00110 Relation sdepRel;
00111
00112
00113
00114
00115 Assert(depender->objectSubId == 0);
00116 Assert(referenced->objectSubId == 0);
00117
00118
00119
00120
00121
00122 if (IsBootstrapProcessingMode())
00123 return;
00124
00125 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
00126
00127
00128 if (!isSharedObjectPinned(referenced->classId, referenced->objectId,
00129 sdepRel))
00130 {
00131 shdepAddDependency(sdepRel, depender->classId, depender->objectId,
00132 depender->objectSubId,
00133 referenced->classId, referenced->objectId,
00134 deptype);
00135 }
00136
00137 heap_close(sdepRel, RowExclusiveLock);
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 void
00150 recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
00151 {
00152 ObjectAddress myself,
00153 referenced;
00154
00155 myself.classId = classId;
00156 myself.objectId = objectId;
00157 myself.objectSubId = 0;
00158
00159 referenced.classId = AuthIdRelationId;
00160 referenced.objectId = owner;
00161 referenced.objectSubId = 0;
00162
00163 recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER);
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 static void
00185 shdepChangeDep(Relation sdepRel,
00186 Oid classid, Oid objid, int32 objsubid,
00187 Oid refclassid, Oid refobjid,
00188 SharedDependencyType deptype)
00189 {
00190 Oid dbid = classIdGetDbId(classid);
00191 HeapTuple oldtup = NULL;
00192 HeapTuple scantup;
00193 ScanKeyData key[4];
00194 SysScanDesc scan;
00195
00196
00197
00198
00199
00200 shdepLockAndCheckObject(refclassid, refobjid);
00201
00202
00203
00204
00205 ScanKeyInit(&key[0],
00206 Anum_pg_shdepend_dbid,
00207 BTEqualStrategyNumber, F_OIDEQ,
00208 ObjectIdGetDatum(dbid));
00209 ScanKeyInit(&key[1],
00210 Anum_pg_shdepend_classid,
00211 BTEqualStrategyNumber, F_OIDEQ,
00212 ObjectIdGetDatum(classid));
00213 ScanKeyInit(&key[2],
00214 Anum_pg_shdepend_objid,
00215 BTEqualStrategyNumber, F_OIDEQ,
00216 ObjectIdGetDatum(objid));
00217 ScanKeyInit(&key[3],
00218 Anum_pg_shdepend_objsubid,
00219 BTEqualStrategyNumber, F_INT4EQ,
00220 Int32GetDatum(objsubid));
00221
00222 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
00223 SnapshotNow, 4, key);
00224
00225 while ((scantup = systable_getnext(scan)) != NULL)
00226 {
00227
00228 if (((Form_pg_shdepend) GETSTRUCT(scantup))->deptype != deptype)
00229 continue;
00230
00231 if (oldtup)
00232 elog(ERROR,
00233 "multiple pg_shdepend entries for object %u/%u/%d deptype %c",
00234 classid, objid, objsubid, deptype);
00235 oldtup = heap_copytuple(scantup);
00236 }
00237
00238 systable_endscan(scan);
00239
00240 if (isSharedObjectPinned(refclassid, refobjid, sdepRel))
00241 {
00242
00243 if (oldtup)
00244 simple_heap_delete(sdepRel, &oldtup->t_self);
00245 }
00246 else if (oldtup)
00247 {
00248
00249 Form_pg_shdepend shForm = (Form_pg_shdepend) GETSTRUCT(oldtup);
00250
00251
00252 shForm->refclassid = refclassid;
00253 shForm->refobjid = refobjid;
00254
00255 simple_heap_update(sdepRel, &oldtup->t_self, oldtup);
00256
00257
00258 CatalogUpdateIndexes(sdepRel, oldtup);
00259 }
00260 else
00261 {
00262
00263 Datum values[Natts_pg_shdepend];
00264 bool nulls[Natts_pg_shdepend];
00265
00266 memset(nulls, false, sizeof(nulls));
00267
00268 values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid);
00269 values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid);
00270 values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid);
00271 values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid);
00272
00273 values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid);
00274 values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid);
00275 values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
00276
00277
00278
00279
00280
00281 oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls);
00282 simple_heap_insert(sdepRel, oldtup);
00283
00284
00285 CatalogUpdateIndexes(sdepRel, oldtup);
00286 }
00287
00288 if (oldtup)
00289 heap_freetuple(oldtup);
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 void
00301 changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
00302 {
00303 Relation sdepRel;
00304
00305 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
00306
00307
00308 shdepChangeDep(sdepRel,
00309 classId, objectId, 0,
00310 AuthIdRelationId, newOwnerId,
00311 SHARED_DEPENDENCY_OWNER);
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 shdepDropDependency(sdepRel, classId, objectId, 0, true,
00333 AuthIdRelationId, newOwnerId,
00334 SHARED_DEPENDENCY_ACL);
00335
00336 heap_close(sdepRel, RowExclusiveLock);
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 static void
00348 getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
00349 {
00350 int in1,
00351 in2,
00352 out1,
00353 out2;
00354
00355 in1 = in2 = out1 = out2 = 0;
00356 while (in1 < *nlist1 && in2 < *nlist2)
00357 {
00358 if (list1[in1] == list2[in2])
00359 {
00360
00361 in1++;
00362 in2++;
00363 }
00364 else if (list1[in1] < list2[in2])
00365 {
00366
00367 list1[out1++] = list1[in1++];
00368 }
00369 else
00370 {
00371
00372 list2[out2++] = list2[in2++];
00373 }
00374 }
00375
00376
00377 while (in1 < *nlist1)
00378 {
00379 list1[out1++] = list1[in1++];
00380 }
00381
00382
00383 while (in2 < *nlist2)
00384 {
00385 list2[out2++] = list2[in2++];
00386 }
00387
00388 *nlist1 = out1;
00389 *nlist2 = out2;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 void
00418 updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
00419 Oid ownerId,
00420 int noldmembers, Oid *oldmembers,
00421 int nnewmembers, Oid *newmembers)
00422 {
00423 Relation sdepRel;
00424 int i;
00425
00426
00427
00428
00429
00430
00431
00432 getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
00433
00434 if (noldmembers > 0 || nnewmembers > 0)
00435 {
00436 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
00437
00438
00439 for (i = 0; i < nnewmembers; i++)
00440 {
00441 Oid roleid = newmembers[i];
00442
00443
00444
00445
00446
00447
00448 if (roleid == ownerId)
00449 continue;
00450
00451
00452 if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
00453 continue;
00454
00455 shdepAddDependency(sdepRel, classId, objectId, objsubId,
00456 AuthIdRelationId, roleid,
00457 SHARED_DEPENDENCY_ACL);
00458 }
00459
00460
00461 for (i = 0; i < noldmembers; i++)
00462 {
00463 Oid roleid = oldmembers[i];
00464
00465
00466 if (roleid == ownerId)
00467 continue;
00468
00469
00470 if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
00471 continue;
00472
00473 shdepDropDependency(sdepRel, classId, objectId, objsubId,
00474 false,
00475 AuthIdRelationId, roleid,
00476 SHARED_DEPENDENCY_ACL);
00477 }
00478
00479 heap_close(sdepRel, RowExclusiveLock);
00480 }
00481
00482 if (oldmembers)
00483 pfree(oldmembers);
00484 if (newmembers)
00485 pfree(newmembers);
00486 }
00487
00488
00489
00490
00491 typedef struct
00492 {
00493 Oid dbOid;
00494 int count;
00495 } remoteDep;
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 bool
00519 checkSharedDependencies(Oid classId, Oid objectId,
00520 char **detail_msg, char **detail_log_msg)
00521 {
00522 Relation sdepRel;
00523 ScanKeyData key[2];
00524 SysScanDesc scan;
00525 HeapTuple tup;
00526 int numReportedDeps = 0;
00527 int numNotReportedDeps = 0;
00528 int numNotReportedDbs = 0;
00529 List *remDeps = NIL;
00530 ListCell *cell;
00531 ObjectAddress object;
00532 StringInfoData descs;
00533 StringInfoData alldescs;
00534
00535
00536
00537
00538
00539
00540 #define MAX_REPORTED_DEPS 100
00541
00542 initStringInfo(&descs);
00543 initStringInfo(&alldescs);
00544
00545 sdepRel = heap_open(SharedDependRelationId, AccessShareLock);
00546
00547 ScanKeyInit(&key[0],
00548 Anum_pg_shdepend_refclassid,
00549 BTEqualStrategyNumber, F_OIDEQ,
00550 ObjectIdGetDatum(classId));
00551 ScanKeyInit(&key[1],
00552 Anum_pg_shdepend_refobjid,
00553 BTEqualStrategyNumber, F_OIDEQ,
00554 ObjectIdGetDatum(objectId));
00555
00556 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
00557 SnapshotNow, 2, key);
00558
00559 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00560 {
00561 Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
00562
00563
00564 if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
00565 {
00566 object.classId = classId;
00567 object.objectId = objectId;
00568 object.objectSubId = 0;
00569 ereport(ERROR,
00570 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00571 errmsg("cannot drop %s because it is required by the database system",
00572 getObjectDescription(&object))));
00573 }
00574
00575 object.classId = sdepForm->classid;
00576 object.objectId = sdepForm->objid;
00577 object.objectSubId = sdepForm->objsubid;
00578
00579
00580
00581
00582
00583
00584
00585
00586 if (sdepForm->dbid == MyDatabaseId)
00587 {
00588 if (numReportedDeps < MAX_REPORTED_DEPS)
00589 {
00590 numReportedDeps++;
00591 storeObjectDescription(&descs, LOCAL_OBJECT, &object,
00592 sdepForm->deptype, 0);
00593 }
00594 else
00595 numNotReportedDeps++;
00596 storeObjectDescription(&alldescs, LOCAL_OBJECT, &object,
00597 sdepForm->deptype, 0);
00598 }
00599 else if (sdepForm->dbid == InvalidOid)
00600 {
00601 if (numReportedDeps < MAX_REPORTED_DEPS)
00602 {
00603 numReportedDeps++;
00604 storeObjectDescription(&descs, SHARED_OBJECT, &object,
00605 sdepForm->deptype, 0);
00606 }
00607 else
00608 numNotReportedDeps++;
00609 storeObjectDescription(&alldescs, SHARED_OBJECT, &object,
00610 sdepForm->deptype, 0);
00611 }
00612 else
00613 {
00614
00615 remoteDep *dep;
00616 bool stored = false;
00617
00618
00619
00620
00621
00622
00623
00624 foreach(cell, remDeps)
00625 {
00626 dep = lfirst(cell);
00627 if (dep->dbOid == sdepForm->dbid)
00628 {
00629 dep->count++;
00630 stored = true;
00631 break;
00632 }
00633 }
00634 if (!stored)
00635 {
00636 dep = (remoteDep *) palloc(sizeof(remoteDep));
00637 dep->dbOid = sdepForm->dbid;
00638 dep->count = 1;
00639 remDeps = lappend(remDeps, dep);
00640 }
00641 }
00642 }
00643
00644 systable_endscan(scan);
00645
00646 heap_close(sdepRel, AccessShareLock);
00647
00648
00649
00650
00651 foreach(cell, remDeps)
00652 {
00653 remoteDep *dep = lfirst(cell);
00654
00655 object.classId = DatabaseRelationId;
00656 object.objectId = dep->dbOid;
00657 object.objectSubId = 0;
00658
00659 if (numReportedDeps < MAX_REPORTED_DEPS)
00660 {
00661 numReportedDeps++;
00662 storeObjectDescription(&descs, REMOTE_OBJECT, &object,
00663 SHARED_DEPENDENCY_INVALID, dep->count);
00664 }
00665 else
00666 numNotReportedDbs++;
00667 storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
00668 SHARED_DEPENDENCY_INVALID, dep->count);
00669 }
00670
00671 list_free_deep(remDeps);
00672
00673 if (descs.len == 0)
00674 {
00675 pfree(descs.data);
00676 pfree(alldescs.data);
00677 *detail_msg = *detail_log_msg = NULL;
00678 return false;
00679 }
00680
00681 if (numNotReportedDeps > 0)
00682 appendStringInfo(&descs, ngettext("\nand %d other object "
00683 "(see server log for list)",
00684 "\nand %d other objects "
00685 "(see server log for list)",
00686 numNotReportedDeps),
00687 numNotReportedDeps);
00688 if (numNotReportedDbs > 0)
00689 appendStringInfo(&descs, ngettext("\nand objects in %d other database "
00690 "(see server log for list)",
00691 "\nand objects in %d other databases "
00692 "(see server log for list)",
00693 numNotReportedDbs),
00694 numNotReportedDbs);
00695
00696 *detail_msg = descs.data;
00697 *detail_log_msg = alldescs.data;
00698 return true;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707 void
00708 copyTemplateDependencies(Oid templateDbId, Oid newDbId)
00709 {
00710 Relation sdepRel;
00711 TupleDesc sdepDesc;
00712 ScanKeyData key[1];
00713 SysScanDesc scan;
00714 HeapTuple tup;
00715 CatalogIndexState indstate;
00716 Datum values[Natts_pg_shdepend];
00717 bool nulls[Natts_pg_shdepend];
00718 bool replace[Natts_pg_shdepend];
00719
00720 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
00721 sdepDesc = RelationGetDescr(sdepRel);
00722
00723 indstate = CatalogOpenIndexes(sdepRel);
00724
00725
00726 ScanKeyInit(&key[0],
00727 Anum_pg_shdepend_dbid,
00728 BTEqualStrategyNumber, F_OIDEQ,
00729 ObjectIdGetDatum(templateDbId));
00730
00731 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
00732 SnapshotNow, 1, key);
00733
00734
00735 memset(values, 0, sizeof(values));
00736 memset(nulls, false, sizeof(nulls));
00737 memset(replace, false, sizeof(replace));
00738
00739 replace[Anum_pg_shdepend_dbid - 1] = true;
00740 values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);
00741
00742
00743
00744
00745
00746
00747
00748
00749 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00750 {
00751 HeapTuple newtup;
00752
00753 newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace);
00754 simple_heap_insert(sdepRel, newtup);
00755
00756
00757 CatalogIndexInsert(indstate, newtup);
00758
00759 heap_freetuple(newtup);
00760 }
00761
00762 systable_endscan(scan);
00763
00764 CatalogCloseIndexes(indstate);
00765 heap_close(sdepRel, RowExclusiveLock);
00766 }
00767
00768
00769
00770
00771
00772
00773
00774 void
00775 dropDatabaseDependencies(Oid databaseId)
00776 {
00777 Relation sdepRel;
00778 ScanKeyData key[1];
00779 SysScanDesc scan;
00780 HeapTuple tup;
00781
00782 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
00783
00784
00785
00786
00787
00788 ScanKeyInit(&key[0],
00789 Anum_pg_shdepend_dbid,
00790 BTEqualStrategyNumber, F_OIDEQ,
00791 ObjectIdGetDatum(databaseId));
00792
00793
00794 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
00795 SnapshotNow, 1, key);
00796
00797 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00798 {
00799 simple_heap_delete(sdepRel, &tup->t_self);
00800 }
00801
00802 systable_endscan(scan);
00803
00804
00805 shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
00806 InvalidOid, InvalidOid,
00807 SHARED_DEPENDENCY_INVALID);
00808
00809 heap_close(sdepRel, RowExclusiveLock);
00810 }
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 void
00823 deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
00824 {
00825 Relation sdepRel;
00826
00827 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
00828
00829 shdepDropDependency(sdepRel, classId, objectId, objectSubId,
00830 (objectSubId == 0),
00831 InvalidOid, InvalidOid,
00832 SHARED_DEPENDENCY_INVALID);
00833
00834 heap_close(sdepRel, RowExclusiveLock);
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844 static void
00845 shdepAddDependency(Relation sdepRel,
00846 Oid classId, Oid objectId, int32 objsubId,
00847 Oid refclassId, Oid refobjId,
00848 SharedDependencyType deptype)
00849 {
00850 HeapTuple tup;
00851 Datum values[Natts_pg_shdepend];
00852 bool nulls[Natts_pg_shdepend];
00853
00854
00855
00856
00857
00858
00859 shdepLockAndCheckObject(refclassId, refobjId);
00860
00861 memset(nulls, false, sizeof(nulls));
00862
00863
00864
00865
00866 values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
00867 values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
00868 values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
00869 values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
00870
00871 values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
00872 values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
00873 values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
00874
00875 tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
00876
00877 simple_heap_insert(sdepRel, tup);
00878
00879
00880 CatalogUpdateIndexes(sdepRel, tup);
00881
00882
00883 heap_freetuple(tup);
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 static void
00903 shdepDropDependency(Relation sdepRel,
00904 Oid classId, Oid objectId, int32 objsubId,
00905 bool drop_subobjects,
00906 Oid refclassId, Oid refobjId,
00907 SharedDependencyType deptype)
00908 {
00909 ScanKeyData key[4];
00910 int nkeys;
00911 SysScanDesc scan;
00912 HeapTuple tup;
00913
00914
00915 ScanKeyInit(&key[0],
00916 Anum_pg_shdepend_dbid,
00917 BTEqualStrategyNumber, F_OIDEQ,
00918 ObjectIdGetDatum(classIdGetDbId(classId)));
00919 ScanKeyInit(&key[1],
00920 Anum_pg_shdepend_classid,
00921 BTEqualStrategyNumber, F_OIDEQ,
00922 ObjectIdGetDatum(classId));
00923 ScanKeyInit(&key[2],
00924 Anum_pg_shdepend_objid,
00925 BTEqualStrategyNumber, F_OIDEQ,
00926 ObjectIdGetDatum(objectId));
00927 if (drop_subobjects)
00928 nkeys = 3;
00929 else
00930 {
00931 ScanKeyInit(&key[3],
00932 Anum_pg_shdepend_objsubid,
00933 BTEqualStrategyNumber, F_INT4EQ,
00934 Int32GetDatum(objsubId));
00935 nkeys = 4;
00936 }
00937
00938 scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
00939 SnapshotNow, nkeys, key);
00940
00941 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00942 {
00943 Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
00944
00945
00946 if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
00947 continue;
00948 if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
00949 continue;
00950 if (deptype != SHARED_DEPENDENCY_INVALID &&
00951 shdepForm->deptype != deptype)
00952 continue;
00953
00954
00955 simple_heap_delete(sdepRel, &tup->t_self);
00956 }
00957
00958 systable_endscan(scan);
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968 static Oid
00969 classIdGetDbId(Oid classId)
00970 {
00971 Oid dbId;
00972
00973 if (IsSharedRelation(classId))
00974 dbId = InvalidOid;
00975 else
00976 dbId = MyDatabaseId;
00977
00978 return dbId;
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 void
00990 shdepLockAndCheckObject(Oid classId, Oid objectId)
00991 {
00992
00993 LockSharedObject(classId, objectId, 0, AccessShareLock);
00994
00995 switch (classId)
00996 {
00997 case AuthIdRelationId:
00998 if (!SearchSysCacheExists1(AUTHOID, ObjectIdGetDatum(objectId)))
00999 ereport(ERROR,
01000 (errcode(ERRCODE_UNDEFINED_OBJECT),
01001 errmsg("role %u was concurrently dropped",
01002 objectId)));
01003 break;
01004
01005
01006
01007
01008
01009
01010
01011 #ifdef NOT_USED
01012 case TableSpaceRelationId:
01013 {
01014
01015 char *tablespace = get_tablespace_name(objectId);
01016
01017 if (tablespace == NULL)
01018 ereport(ERROR,
01019 (errcode(ERRCODE_UNDEFINED_OBJECT),
01020 errmsg("tablespace %u was concurrently dropped",
01021 objectId)));
01022 pfree(tablespace);
01023 break;
01024 }
01025 #endif
01026
01027 case DatabaseRelationId:
01028 {
01029
01030 char *database = get_database_name(objectId);
01031
01032 if (database == NULL)
01033 ereport(ERROR,
01034 (errcode(ERRCODE_UNDEFINED_OBJECT),
01035 errmsg("database %u was concurrently dropped",
01036 objectId)));
01037 pfree(database);
01038 break;
01039 }
01040
01041
01042 default:
01043 elog(ERROR, "unrecognized shared classId: %u", classId);
01044 }
01045 }
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static void
01063 storeObjectDescription(StringInfo descs, objectType type,
01064 ObjectAddress *object,
01065 SharedDependencyType deptype,
01066 int count)
01067 {
01068 char *objdesc = getObjectDescription(object);
01069
01070
01071 if (descs->len != 0)
01072 appendStringInfoChar(descs, '\n');
01073
01074 switch (type)
01075 {
01076 case LOCAL_OBJECT:
01077 case SHARED_OBJECT:
01078 if (deptype == SHARED_DEPENDENCY_OWNER)
01079 appendStringInfo(descs, _("owner of %s"), objdesc);
01080 else if (deptype == SHARED_DEPENDENCY_ACL)
01081 appendStringInfo(descs, _("privileges for %s"), objdesc);
01082 else
01083 elog(ERROR, "unrecognized dependency type: %d",
01084 (int) deptype);
01085 break;
01086
01087 case REMOTE_OBJECT:
01088
01089 appendStringInfo(descs, ngettext("%d object in %s",
01090 "%d objects in %s",
01091 count),
01092 count, objdesc);
01093 break;
01094
01095 default:
01096 elog(ERROR, "unrecognized object type: %d", type);
01097 }
01098
01099 pfree(objdesc);
01100 }
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 static bool
01111 isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
01112 {
01113 bool result = false;
01114 ScanKeyData key[2];
01115 SysScanDesc scan;
01116 HeapTuple tup;
01117
01118 ScanKeyInit(&key[0],
01119 Anum_pg_shdepend_refclassid,
01120 BTEqualStrategyNumber, F_OIDEQ,
01121 ObjectIdGetDatum(classId));
01122 ScanKeyInit(&key[1],
01123 Anum_pg_shdepend_refobjid,
01124 BTEqualStrategyNumber, F_OIDEQ,
01125 ObjectIdGetDatum(objectId));
01126
01127 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
01128 SnapshotNow, 2, key);
01129
01130
01131
01132
01133
01134
01135
01136 tup = systable_getnext(scan);
01137 if (HeapTupleIsValid(tup))
01138 {
01139 Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
01140
01141 if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
01142 result = true;
01143 }
01144
01145 systable_endscan(scan);
01146
01147 return result;
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 void
01163 shdepDropOwned(List *roleids, DropBehavior behavior)
01164 {
01165 Relation sdepRel;
01166 ListCell *cell;
01167 ObjectAddresses *deleteobjs;
01168
01169 deleteobjs = new_object_addresses();
01170
01171
01172
01173
01174
01175
01176 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
01177
01178
01179
01180
01181
01182 foreach(cell, roleids)
01183 {
01184 Oid roleid = lfirst_oid(cell);
01185 ScanKeyData key[2];
01186 SysScanDesc scan;
01187 HeapTuple tuple;
01188
01189
01190 if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
01191 {
01192 ObjectAddress obj;
01193
01194 obj.classId = AuthIdRelationId;
01195 obj.objectId = roleid;
01196 obj.objectSubId = 0;
01197
01198 ereport(ERROR,
01199 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
01200 errmsg("cannot drop objects owned by %s because they are "
01201 "required by the database system",
01202 getObjectDescription(&obj))));
01203 }
01204
01205 ScanKeyInit(&key[0],
01206 Anum_pg_shdepend_refclassid,
01207 BTEqualStrategyNumber, F_OIDEQ,
01208 ObjectIdGetDatum(AuthIdRelationId));
01209 ScanKeyInit(&key[1],
01210 Anum_pg_shdepend_refobjid,
01211 BTEqualStrategyNumber, F_OIDEQ,
01212 ObjectIdGetDatum(roleid));
01213
01214 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
01215 SnapshotNow, 2, key);
01216
01217 while ((tuple = systable_getnext(scan)) != NULL)
01218 {
01219 Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
01220 ObjectAddress obj;
01221
01222
01223
01224
01225
01226 if (sdepForm->dbid != MyDatabaseId &&
01227 sdepForm->dbid != InvalidOid)
01228 continue;
01229
01230 switch (sdepForm->deptype)
01231 {
01232
01233 case SHARED_DEPENDENCY_PIN:
01234 case SHARED_DEPENDENCY_INVALID:
01235 elog(ERROR, "unexpected dependency type");
01236 break;
01237 case SHARED_DEPENDENCY_ACL:
01238 RemoveRoleFromObjectACL(roleid,
01239 sdepForm->classid,
01240 sdepForm->objid);
01241 break;
01242 case SHARED_DEPENDENCY_OWNER:
01243
01244 if (sdepForm->dbid == MyDatabaseId)
01245 {
01246 obj.classId = sdepForm->classid;
01247 obj.objectId = sdepForm->objid;
01248 obj.objectSubId = sdepForm->objsubid;
01249 add_exact_object_address(&obj, deleteobjs);
01250 }
01251 break;
01252 }
01253 }
01254
01255 systable_endscan(scan);
01256 }
01257
01258
01259 performMultipleDeletions(deleteobjs, behavior, 0);
01260
01261 heap_close(sdepRel, RowExclusiveLock);
01262
01263 free_object_addresses(deleteobjs);
01264 }
01265
01266
01267
01268
01269
01270
01271
01272 void
01273 shdepReassignOwned(List *roleids, Oid newrole)
01274 {
01275 Relation sdepRel;
01276 ListCell *cell;
01277
01278
01279
01280
01281
01282
01283 sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
01284
01285 foreach(cell, roleids)
01286 {
01287 SysScanDesc scan;
01288 ScanKeyData key[2];
01289 HeapTuple tuple;
01290 Oid roleid = lfirst_oid(cell);
01291
01292
01293 if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
01294 {
01295 ObjectAddress obj;
01296
01297 obj.classId = AuthIdRelationId;
01298 obj.objectId = roleid;
01299 obj.objectSubId = 0;
01300
01301 ereport(ERROR,
01302 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
01303 errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
01304 getObjectDescription(&obj))));
01305
01306
01307
01308
01309
01310 }
01311
01312 ScanKeyInit(&key[0],
01313 Anum_pg_shdepend_refclassid,
01314 BTEqualStrategyNumber, F_OIDEQ,
01315 ObjectIdGetDatum(AuthIdRelationId));
01316 ScanKeyInit(&key[1],
01317 Anum_pg_shdepend_refobjid,
01318 BTEqualStrategyNumber, F_OIDEQ,
01319 ObjectIdGetDatum(roleid));
01320
01321 scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
01322 SnapshotNow, 2, key);
01323
01324 while ((tuple = systable_getnext(scan)) != NULL)
01325 {
01326 Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
01327
01328
01329
01330
01331
01332 if (sdepForm->dbid != MyDatabaseId &&
01333 sdepForm->dbid != InvalidOid)
01334 continue;
01335
01336
01337 if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
01338 elog(ERROR, "unexpected shared pin");
01339
01340
01341 if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
01342 continue;
01343
01344
01345 switch (sdepForm->classid)
01346 {
01347 case TypeRelationId:
01348 AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
01349 break;
01350
01351 case NamespaceRelationId:
01352 AlterSchemaOwner_oid(sdepForm->objid, newrole);
01353 break;
01354
01355 case RelationRelationId:
01356
01357
01358
01359
01360
01361
01362 ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
01363 break;
01364
01365 case DefaultAclRelationId:
01366
01367
01368
01369
01370
01371 break;
01372
01373 case ForeignServerRelationId:
01374 AlterForeignServerOwner_oid(sdepForm->objid, newrole);
01375 break;
01376
01377 case ForeignDataWrapperRelationId:
01378 AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
01379 break;
01380
01381 case EventTriggerRelationId:
01382 AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
01383 break;
01384
01385
01386 case CollationRelationId:
01387 case ConversionRelationId:
01388 case OperatorRelationId:
01389 case ProcedureRelationId:
01390 case LanguageRelationId:
01391 case LargeObjectRelationId:
01392 case OperatorFamilyRelationId:
01393 case OperatorClassRelationId:
01394 case ExtensionRelationId:
01395 case TableSpaceRelationId:
01396 case DatabaseRelationId:
01397 {
01398 Oid classId = sdepForm->classid;
01399 Relation catalog;
01400
01401 if (classId == LargeObjectRelationId)
01402 classId = LargeObjectMetadataRelationId;
01403
01404 catalog = heap_open(classId, RowExclusiveLock);
01405
01406 AlterObjectOwner_internal(catalog, sdepForm->objid,
01407 newrole);
01408
01409 heap_close(catalog, NoLock);
01410 }
01411 break;
01412
01413 default:
01414 elog(ERROR, "unexpected classid %u", sdepForm->classid);
01415 break;
01416 }
01417
01418 CommandCounterIncrement();
01419 }
01420
01421 systable_endscan(scan);
01422 }
01423
01424 heap_close(sdepRel, RowExclusiveLock);
01425 }