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 "catalog/dependency.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/pg_constraint.h"
00023 #include "catalog/pg_depend.h"
00024 #include "catalog/pg_extension.h"
00025 #include "commands/extension.h"
00026 #include "miscadmin.h"
00027 #include "utils/fmgroids.h"
00028 #include "utils/lsyscache.h"
00029 #include "utils/rel.h"
00030 #include "utils/tqual.h"
00031
00032
00033 static bool isObjectPinned(const ObjectAddress *object, Relation rel);
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 void
00044 recordDependencyOn(const ObjectAddress *depender,
00045 const ObjectAddress *referenced,
00046 DependencyType behavior)
00047 {
00048 recordMultipleDependencies(depender, referenced, 1, behavior);
00049 }
00050
00051
00052
00053
00054
00055 void
00056 recordMultipleDependencies(const ObjectAddress *depender,
00057 const ObjectAddress *referenced,
00058 int nreferenced,
00059 DependencyType behavior)
00060 {
00061 Relation dependDesc;
00062 CatalogIndexState indstate;
00063 HeapTuple tup;
00064 int i;
00065 bool nulls[Natts_pg_depend];
00066 Datum values[Natts_pg_depend];
00067
00068 if (nreferenced <= 0)
00069 return;
00070
00071
00072
00073
00074
00075 if (IsBootstrapProcessingMode())
00076 return;
00077
00078 dependDesc = heap_open(DependRelationId, RowExclusiveLock);
00079
00080
00081 indstate = NULL;
00082
00083 memset(nulls, false, sizeof(nulls));
00084
00085 for (i = 0; i < nreferenced; i++, referenced++)
00086 {
00087
00088
00089
00090
00091
00092 if (!isObjectPinned(referenced, dependDesc))
00093 {
00094
00095
00096
00097
00098 values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
00099 values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
00100 values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
00101
00102 values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
00103 values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
00104 values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
00105
00106 values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
00107
00108 tup = heap_form_tuple(dependDesc->rd_att, values, nulls);
00109
00110 simple_heap_insert(dependDesc, tup);
00111
00112
00113 if (indstate == NULL)
00114 indstate = CatalogOpenIndexes(dependDesc);
00115
00116 CatalogIndexInsert(indstate, tup);
00117
00118 heap_freetuple(tup);
00119 }
00120 }
00121
00122 if (indstate != NULL)
00123 CatalogCloseIndexes(indstate);
00124
00125 heap_close(dependDesc, RowExclusiveLock);
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 void
00141 recordDependencyOnCurrentExtension(const ObjectAddress *object,
00142 bool isReplace)
00143 {
00144
00145 Assert(object->objectSubId == 0);
00146
00147 if (creating_extension)
00148 {
00149 ObjectAddress extension;
00150
00151
00152 if (isReplace)
00153 {
00154 Oid oldext;
00155
00156 oldext = getExtensionOfObject(object->classId, object->objectId);
00157 if (OidIsValid(oldext))
00158 {
00159
00160 if (oldext == CurrentExtensionObject)
00161 return;
00162
00163 ereport(ERROR,
00164 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00165 errmsg("%s is already a member of extension \"%s\"",
00166 getObjectDescription(object),
00167 get_extension_name(oldext))));
00168 }
00169 }
00170
00171
00172 extension.classId = ExtensionRelationId;
00173 extension.objectId = CurrentExtensionObject;
00174 extension.objectSubId = 0;
00175
00176 recordDependencyOn(object, &extension, DEPENDENCY_EXTENSION);
00177 }
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 long
00193 deleteDependencyRecordsFor(Oid classId, Oid objectId,
00194 bool skipExtensionDeps)
00195 {
00196 long count = 0;
00197 Relation depRel;
00198 ScanKeyData key[2];
00199 SysScanDesc scan;
00200 HeapTuple tup;
00201
00202 depRel = heap_open(DependRelationId, RowExclusiveLock);
00203
00204 ScanKeyInit(&key[0],
00205 Anum_pg_depend_classid,
00206 BTEqualStrategyNumber, F_OIDEQ,
00207 ObjectIdGetDatum(classId));
00208 ScanKeyInit(&key[1],
00209 Anum_pg_depend_objid,
00210 BTEqualStrategyNumber, F_OIDEQ,
00211 ObjectIdGetDatum(objectId));
00212
00213 scan = systable_beginscan(depRel, DependDependerIndexId, true,
00214 SnapshotNow, 2, key);
00215
00216 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00217 {
00218 if (skipExtensionDeps &&
00219 ((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
00220 continue;
00221
00222 simple_heap_delete(depRel, &tup->t_self);
00223 count++;
00224 }
00225
00226 systable_endscan(scan);
00227
00228 heap_close(depRel, RowExclusiveLock);
00229
00230 return count;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 long
00243 deleteDependencyRecordsForClass(Oid classId, Oid objectId,
00244 Oid refclassId, char deptype)
00245 {
00246 long count = 0;
00247 Relation depRel;
00248 ScanKeyData key[2];
00249 SysScanDesc scan;
00250 HeapTuple tup;
00251
00252 depRel = heap_open(DependRelationId, RowExclusiveLock);
00253
00254 ScanKeyInit(&key[0],
00255 Anum_pg_depend_classid,
00256 BTEqualStrategyNumber, F_OIDEQ,
00257 ObjectIdGetDatum(classId));
00258 ScanKeyInit(&key[1],
00259 Anum_pg_depend_objid,
00260 BTEqualStrategyNumber, F_OIDEQ,
00261 ObjectIdGetDatum(objectId));
00262
00263 scan = systable_beginscan(depRel, DependDependerIndexId, true,
00264 SnapshotNow, 2, key);
00265
00266 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00267 {
00268 Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
00269
00270 if (depform->refclassid == refclassId && depform->deptype == deptype)
00271 {
00272 simple_heap_delete(depRel, &tup->t_self);
00273 count++;
00274 }
00275 }
00276
00277 systable_endscan(scan);
00278
00279 heap_close(depRel, RowExclusiveLock);
00280
00281 return count;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 long
00297 changeDependencyFor(Oid classId, Oid objectId,
00298 Oid refClassId, Oid oldRefObjectId,
00299 Oid newRefObjectId)
00300 {
00301 long count = 0;
00302 Relation depRel;
00303 ScanKeyData key[2];
00304 SysScanDesc scan;
00305 HeapTuple tup;
00306 ObjectAddress objAddr;
00307 bool newIsPinned;
00308
00309 depRel = heap_open(DependRelationId, RowExclusiveLock);
00310
00311
00312
00313
00314
00315
00316
00317 objAddr.classId = refClassId;
00318 objAddr.objectId = oldRefObjectId;
00319 objAddr.objectSubId = 0;
00320
00321 if (isObjectPinned(&objAddr, depRel))
00322 ereport(ERROR,
00323 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00324 errmsg("cannot remove dependency on %s because it is a system object",
00325 getObjectDescription(&objAddr))));
00326
00327
00328
00329
00330
00331 objAddr.objectId = newRefObjectId;
00332
00333 newIsPinned = isObjectPinned(&objAddr, depRel);
00334
00335
00336 ScanKeyInit(&key[0],
00337 Anum_pg_depend_classid,
00338 BTEqualStrategyNumber, F_OIDEQ,
00339 ObjectIdGetDatum(classId));
00340 ScanKeyInit(&key[1],
00341 Anum_pg_depend_objid,
00342 BTEqualStrategyNumber, F_OIDEQ,
00343 ObjectIdGetDatum(objectId));
00344
00345 scan = systable_beginscan(depRel, DependDependerIndexId, true,
00346 SnapshotNow, 2, key);
00347
00348 while (HeapTupleIsValid((tup = systable_getnext(scan))))
00349 {
00350 Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
00351
00352 if (depform->refclassid == refClassId &&
00353 depform->refobjid == oldRefObjectId)
00354 {
00355 if (newIsPinned)
00356 simple_heap_delete(depRel, &tup->t_self);
00357 else
00358 {
00359
00360 tup = heap_copytuple(tup);
00361 depform = (Form_pg_depend) GETSTRUCT(tup);
00362
00363 depform->refobjid = newRefObjectId;
00364
00365 simple_heap_update(depRel, &tup->t_self, tup);
00366 CatalogUpdateIndexes(depRel, tup);
00367
00368 heap_freetuple(tup);
00369 }
00370
00371 count++;
00372 }
00373 }
00374
00375 systable_endscan(scan);
00376
00377 heap_close(depRel, RowExclusiveLock);
00378
00379 return count;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 static bool
00392 isObjectPinned(const ObjectAddress *object, Relation rel)
00393 {
00394 bool ret = false;
00395 SysScanDesc scan;
00396 HeapTuple tup;
00397 ScanKeyData key[2];
00398
00399 ScanKeyInit(&key[0],
00400 Anum_pg_depend_refclassid,
00401 BTEqualStrategyNumber, F_OIDEQ,
00402 ObjectIdGetDatum(object->classId));
00403
00404 ScanKeyInit(&key[1],
00405 Anum_pg_depend_refobjid,
00406 BTEqualStrategyNumber, F_OIDEQ,
00407 ObjectIdGetDatum(object->objectId));
00408
00409 scan = systable_beginscan(rel, DependReferenceIndexId, true,
00410 SnapshotNow, 2, key);
00411
00412
00413
00414
00415
00416
00417
00418 tup = systable_getnext(scan);
00419 if (HeapTupleIsValid(tup))
00420 {
00421 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
00422
00423 if (foundDep->deptype == DEPENDENCY_PIN)
00424 ret = true;
00425 }
00426
00427 systable_endscan(scan);
00428
00429 return ret;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 Oid
00450 getExtensionOfObject(Oid classId, Oid objectId)
00451 {
00452 Oid result = InvalidOid;
00453 Relation depRel;
00454 ScanKeyData key[2];
00455 SysScanDesc scan;
00456 HeapTuple tup;
00457
00458 depRel = heap_open(DependRelationId, AccessShareLock);
00459
00460 ScanKeyInit(&key[0],
00461 Anum_pg_depend_classid,
00462 BTEqualStrategyNumber, F_OIDEQ,
00463 ObjectIdGetDatum(classId));
00464 ScanKeyInit(&key[1],
00465 Anum_pg_depend_objid,
00466 BTEqualStrategyNumber, F_OIDEQ,
00467 ObjectIdGetDatum(objectId));
00468
00469 scan = systable_beginscan(depRel, DependDependerIndexId, true,
00470 SnapshotNow, 2, key);
00471
00472 while (HeapTupleIsValid((tup = systable_getnext(scan))))
00473 {
00474 Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
00475
00476 if (depform->refclassid == ExtensionRelationId &&
00477 depform->deptype == DEPENDENCY_EXTENSION)
00478 {
00479 result = depform->refobjid;
00480 break;
00481 }
00482 }
00483
00484 systable_endscan(scan);
00485
00486 heap_close(depRel, AccessShareLock);
00487
00488 return result;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 bool
00503 sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
00504 {
00505 bool ret = false;
00506 Relation depRel;
00507 ScanKeyData key[2];
00508 SysScanDesc scan;
00509 HeapTuple tup;
00510
00511 depRel = heap_open(DependRelationId, AccessShareLock);
00512
00513 ScanKeyInit(&key[0],
00514 Anum_pg_depend_classid,
00515 BTEqualStrategyNumber, F_OIDEQ,
00516 ObjectIdGetDatum(RelationRelationId));
00517 ScanKeyInit(&key[1],
00518 Anum_pg_depend_objid,
00519 BTEqualStrategyNumber, F_OIDEQ,
00520 ObjectIdGetDatum(seqId));
00521
00522 scan = systable_beginscan(depRel, DependDependerIndexId, true,
00523 SnapshotNow, 2, key);
00524
00525 while (HeapTupleIsValid((tup = systable_getnext(scan))))
00526 {
00527 Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
00528
00529 if (depform->refclassid == RelationRelationId &&
00530 depform->deptype == DEPENDENCY_AUTO)
00531 {
00532 *tableId = depform->refobjid;
00533 *colId = depform->refobjsubid;
00534 ret = true;
00535 break;
00536 }
00537 }
00538
00539 systable_endscan(scan);
00540
00541 heap_close(depRel, AccessShareLock);
00542
00543 return ret;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 void
00553 markSequenceUnowned(Oid seqId)
00554 {
00555 deleteDependencyRecordsForClass(RelationRelationId, seqId,
00556 RelationRelationId, DEPENDENCY_AUTO);
00557 }
00558
00559
00560
00561
00562 List *
00563 getOwnedSequences(Oid relid)
00564 {
00565 List *result = NIL;
00566 Relation depRel;
00567 ScanKeyData key[2];
00568 SysScanDesc scan;
00569 HeapTuple tup;
00570
00571 depRel = heap_open(DependRelationId, AccessShareLock);
00572
00573 ScanKeyInit(&key[0],
00574 Anum_pg_depend_refclassid,
00575 BTEqualStrategyNumber, F_OIDEQ,
00576 ObjectIdGetDatum(RelationRelationId));
00577 ScanKeyInit(&key[1],
00578 Anum_pg_depend_refobjid,
00579 BTEqualStrategyNumber, F_OIDEQ,
00580 ObjectIdGetDatum(relid));
00581
00582 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
00583 SnapshotNow, 2, key);
00584
00585 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00586 {
00587 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
00588
00589
00590
00591
00592
00593
00594 if (deprec->classid == RelationRelationId &&
00595 deprec->objsubid == 0 &&
00596 deprec->refobjsubid != 0 &&
00597 deprec->deptype == DEPENDENCY_AUTO &&
00598 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
00599 {
00600 result = lappend_oid(result, deprec->objid);
00601 }
00602 }
00603
00604 systable_endscan(scan);
00605
00606 heap_close(depRel, AccessShareLock);
00607
00608 return result;
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 Oid
00621 get_constraint_index(Oid constraintId)
00622 {
00623 Oid indexId = InvalidOid;
00624 Relation depRel;
00625 ScanKeyData key[3];
00626 SysScanDesc scan;
00627 HeapTuple tup;
00628
00629
00630 depRel = heap_open(DependRelationId, AccessShareLock);
00631
00632 ScanKeyInit(&key[0],
00633 Anum_pg_depend_refclassid,
00634 BTEqualStrategyNumber, F_OIDEQ,
00635 ObjectIdGetDatum(ConstraintRelationId));
00636 ScanKeyInit(&key[1],
00637 Anum_pg_depend_refobjid,
00638 BTEqualStrategyNumber, F_OIDEQ,
00639 ObjectIdGetDatum(constraintId));
00640 ScanKeyInit(&key[2],
00641 Anum_pg_depend_refobjsubid,
00642 BTEqualStrategyNumber, F_INT4EQ,
00643 Int32GetDatum(0));
00644
00645 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
00646 SnapshotNow, 3, key);
00647
00648 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00649 {
00650 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
00651
00652
00653
00654
00655
00656
00657 if (deprec->classid == RelationRelationId &&
00658 deprec->objsubid == 0 &&
00659 deprec->deptype == DEPENDENCY_INTERNAL &&
00660 get_rel_relkind(deprec->objid) == RELKIND_INDEX)
00661 {
00662 indexId = deprec->objid;
00663 break;
00664 }
00665 }
00666
00667 systable_endscan(scan);
00668 heap_close(depRel, AccessShareLock);
00669
00670 return indexId;
00671 }
00672
00673
00674
00675
00676
00677
00678 Oid
00679 get_index_constraint(Oid indexId)
00680 {
00681 Oid constraintId = InvalidOid;
00682 Relation depRel;
00683 ScanKeyData key[3];
00684 SysScanDesc scan;
00685 HeapTuple tup;
00686
00687
00688 depRel = heap_open(DependRelationId, AccessShareLock);
00689
00690 ScanKeyInit(&key[0],
00691 Anum_pg_depend_classid,
00692 BTEqualStrategyNumber, F_OIDEQ,
00693 ObjectIdGetDatum(RelationRelationId));
00694 ScanKeyInit(&key[1],
00695 Anum_pg_depend_objid,
00696 BTEqualStrategyNumber, F_OIDEQ,
00697 ObjectIdGetDatum(indexId));
00698 ScanKeyInit(&key[2],
00699 Anum_pg_depend_objsubid,
00700 BTEqualStrategyNumber, F_INT4EQ,
00701 Int32GetDatum(0));
00702
00703 scan = systable_beginscan(depRel, DependDependerIndexId, true,
00704 SnapshotNow, 3, key);
00705
00706 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00707 {
00708 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
00709
00710
00711
00712
00713
00714 if (deprec->refclassid == ConstraintRelationId &&
00715 deprec->refobjsubid == 0 &&
00716 deprec->deptype == DEPENDENCY_INTERNAL)
00717 {
00718 constraintId = deprec->refobjid;
00719 break;
00720 }
00721 }
00722
00723 systable_endscan(scan);
00724 heap_close(depRel, AccessShareLock);
00725
00726 return constraintId;
00727 }