00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/htup_details.h"
00018 #include "access/xact.h"
00019 #include "catalog/dependency.h"
00020 #include "catalog/heap.h"
00021 #include "catalog/index.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_amop.h"
00024 #include "catalog/pg_amproc.h"
00025 #include "catalog/pg_attrdef.h"
00026 #include "catalog/pg_authid.h"
00027 #include "catalog/pg_cast.h"
00028 #include "catalog/pg_collation.h"
00029 #include "catalog/pg_collation_fn.h"
00030 #include "catalog/pg_constraint.h"
00031 #include "catalog/pg_conversion.h"
00032 #include "catalog/pg_conversion_fn.h"
00033 #include "catalog/pg_database.h"
00034 #include "catalog/pg_default_acl.h"
00035 #include "catalog/pg_depend.h"
00036 #include "catalog/pg_event_trigger.h"
00037 #include "catalog/pg_extension.h"
00038 #include "catalog/pg_foreign_data_wrapper.h"
00039 #include "catalog/pg_foreign_server.h"
00040 #include "catalog/pg_language.h"
00041 #include "catalog/pg_largeobject.h"
00042 #include "catalog/pg_namespace.h"
00043 #include "catalog/pg_opclass.h"
00044 #include "catalog/pg_operator.h"
00045 #include "catalog/pg_opfamily.h"
00046 #include "catalog/pg_proc.h"
00047 #include "catalog/pg_rewrite.h"
00048 #include "catalog/pg_tablespace.h"
00049 #include "catalog/pg_trigger.h"
00050 #include "catalog/pg_ts_config.h"
00051 #include "catalog/pg_ts_dict.h"
00052 #include "catalog/pg_ts_parser.h"
00053 #include "catalog/pg_ts_template.h"
00054 #include "catalog/pg_type.h"
00055 #include "catalog/pg_user_mapping.h"
00056 #include "commands/comment.h"
00057 #include "commands/defrem.h"
00058 #include "commands/event_trigger.h"
00059 #include "commands/extension.h"
00060 #include "commands/proclang.h"
00061 #include "commands/schemacmds.h"
00062 #include "commands/seclabel.h"
00063 #include "commands/trigger.h"
00064 #include "commands/typecmds.h"
00065 #include "nodes/nodeFuncs.h"
00066 #include "parser/parsetree.h"
00067 #include "rewrite/rewriteRemove.h"
00068 #include "storage/lmgr.h"
00069 #include "utils/fmgroids.h"
00070 #include "utils/guc.h"
00071 #include "utils/lsyscache.h"
00072 #include "utils/syscache.h"
00073 #include "utils/tqual.h"
00074
00075
00076
00077
00078
00079
00080
00081 typedef struct
00082 {
00083 int flags;
00084 ObjectAddress dependee;
00085 } ObjectAddressExtra;
00086
00087
00088 #define DEPFLAG_ORIGINAL 0x0001
00089 #define DEPFLAG_NORMAL 0x0002
00090 #define DEPFLAG_AUTO 0x0004
00091 #define DEPFLAG_INTERNAL 0x0008
00092 #define DEPFLAG_EXTENSION 0x0010
00093 #define DEPFLAG_REVERSE 0x0020
00094
00095
00096
00097 struct ObjectAddresses
00098 {
00099 ObjectAddress *refs;
00100 ObjectAddressExtra *extras;
00101 int numrefs;
00102 int maxrefs;
00103 };
00104
00105
00106
00107
00108 typedef struct ObjectAddressStack
00109 {
00110 const ObjectAddress *object;
00111 int flags;
00112 struct ObjectAddressStack *next;
00113 } ObjectAddressStack;
00114
00115
00116 typedef struct
00117 {
00118 ObjectAddresses *addrs;
00119 List *rtables;
00120 } find_expr_references_context;
00121
00122
00123
00124
00125
00126 static const Oid object_classes[MAX_OCLASS] = {
00127 RelationRelationId,
00128 ProcedureRelationId,
00129 TypeRelationId,
00130 CastRelationId,
00131 CollationRelationId,
00132 ConstraintRelationId,
00133 ConversionRelationId,
00134 AttrDefaultRelationId,
00135 LanguageRelationId,
00136 LargeObjectRelationId,
00137 OperatorRelationId,
00138 OperatorClassRelationId,
00139 OperatorFamilyRelationId,
00140 AccessMethodOperatorRelationId,
00141 AccessMethodProcedureRelationId,
00142 RewriteRelationId,
00143 TriggerRelationId,
00144 NamespaceRelationId,
00145 TSParserRelationId,
00146 TSDictionaryRelationId,
00147 TSTemplateRelationId,
00148 TSConfigRelationId,
00149 AuthIdRelationId,
00150 DatabaseRelationId,
00151 TableSpaceRelationId,
00152 ForeignDataWrapperRelationId,
00153 ForeignServerRelationId,
00154 UserMappingRelationId,
00155 DefaultAclRelationId,
00156 ExtensionRelationId,
00157 EventTriggerRelationId
00158 };
00159
00160
00161 static void findDependentObjects(const ObjectAddress *object,
00162 int flags,
00163 ObjectAddressStack *stack,
00164 ObjectAddresses *targetObjects,
00165 const ObjectAddresses *pendingObjects,
00166 Relation *depRel);
00167 static void reportDependentObjects(const ObjectAddresses *targetObjects,
00168 DropBehavior behavior,
00169 int msglevel,
00170 const ObjectAddress *origObject);
00171 static void deleteOneObject(const ObjectAddress *object,
00172 Relation *depRel, int32 flags);
00173 static void doDeletion(const ObjectAddress *object, int flags);
00174 static void AcquireDeletionLock(const ObjectAddress *object, int flags);
00175 static void ReleaseDeletionLock(const ObjectAddress *object);
00176 static bool find_expr_references_walker(Node *node,
00177 find_expr_references_context *context);
00178 static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
00179 static int object_address_comparator(const void *a, const void *b);
00180 static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
00181 ObjectAddresses *addrs);
00182 static void add_exact_object_address_extra(const ObjectAddress *object,
00183 const ObjectAddressExtra *extra,
00184 ObjectAddresses *addrs);
00185 static bool object_address_present_add_flags(const ObjectAddress *object,
00186 int flags,
00187 ObjectAddresses *addrs);
00188 static bool stack_address_present_add_flags(const ObjectAddress *object,
00189 int flags,
00190 ObjectAddressStack *stack);
00191
00192
00193
00194
00195
00196
00197 static void
00198 deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
00199 int flags)
00200 {
00201 int i;
00202
00203
00204
00205
00206 if (trackDroppedObjectsNeeded())
00207 {
00208 for (i = 0; i < targetObjects->numrefs; i++)
00209 {
00210 ObjectAddress *thisobj = targetObjects->refs + i;
00211
00212 if ((!(flags & PERFORM_DELETION_INTERNAL)) &&
00213 EventTriggerSupportsObjectClass(getObjectClass(thisobj)))
00214 {
00215 EventTriggerSQLDropAddObject(thisobj);
00216 }
00217 }
00218 }
00219
00220
00221
00222
00223 for (i = 0; i < targetObjects->numrefs; i++)
00224 {
00225 ObjectAddress *thisobj = targetObjects->refs + i;
00226
00227 deleteOneObject(thisobj, depRel, flags);
00228 }
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 void
00251 performDeletion(const ObjectAddress *object,
00252 DropBehavior behavior, int flags)
00253 {
00254 Relation depRel;
00255 ObjectAddresses *targetObjects;
00256
00257
00258
00259
00260
00261 depRel = heap_open(DependRelationId, RowExclusiveLock);
00262
00263
00264
00265
00266
00267 AcquireDeletionLock(object, 0);
00268
00269
00270
00271
00272
00273 targetObjects = new_object_addresses();
00274
00275 findDependentObjects(object,
00276 DEPFLAG_ORIGINAL,
00277 NULL,
00278 targetObjects,
00279 NULL,
00280 &depRel);
00281
00282
00283
00284
00285 reportDependentObjects(targetObjects,
00286 behavior,
00287 NOTICE,
00288 object);
00289
00290
00291 deleteObjectsInList(targetObjects, &depRel, flags);
00292
00293
00294 free_object_addresses(targetObjects);
00295
00296 heap_close(depRel, RowExclusiveLock);
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 void
00309 performMultipleDeletions(const ObjectAddresses *objects,
00310 DropBehavior behavior, int flags)
00311 {
00312 Relation depRel;
00313 ObjectAddresses *targetObjects;
00314 int i;
00315
00316
00317 if (objects->numrefs <= 0)
00318 return;
00319
00320
00321
00322
00323
00324 depRel = heap_open(DependRelationId, RowExclusiveLock);
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 targetObjects = new_object_addresses();
00335
00336 for (i = 0; i < objects->numrefs; i++)
00337 {
00338 const ObjectAddress *thisobj = objects->refs + i;
00339
00340
00341
00342
00343
00344 AcquireDeletionLock(thisobj, flags);
00345
00346 findDependentObjects(thisobj,
00347 DEPFLAG_ORIGINAL,
00348 NULL,
00349 targetObjects,
00350 objects,
00351 &depRel);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 reportDependentObjects(targetObjects,
00361 behavior,
00362 NOTICE,
00363 (objects->numrefs == 1 ? objects->refs : NULL));
00364
00365
00366 deleteObjectsInList(targetObjects, &depRel, flags);
00367
00368
00369 free_object_addresses(targetObjects);
00370
00371 heap_close(depRel, RowExclusiveLock);
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 void
00388 deleteWhatDependsOn(const ObjectAddress *object,
00389 bool showNotices)
00390 {
00391 Relation depRel;
00392 ObjectAddresses *targetObjects;
00393 int i;
00394
00395
00396
00397
00398
00399 depRel = heap_open(DependRelationId, RowExclusiveLock);
00400
00401
00402
00403
00404
00405 AcquireDeletionLock(object, 0);
00406
00407
00408
00409
00410
00411 targetObjects = new_object_addresses();
00412
00413 findDependentObjects(object,
00414 DEPFLAG_ORIGINAL,
00415 NULL,
00416 targetObjects,
00417 NULL,
00418 &depRel);
00419
00420
00421
00422
00423 reportDependentObjects(targetObjects,
00424 DROP_CASCADE,
00425 showNotices ? NOTICE : DEBUG2,
00426 object);
00427
00428
00429
00430
00431
00432 for (i = 0; i < targetObjects->numrefs; i++)
00433 {
00434 ObjectAddress *thisobj = targetObjects->refs + i;
00435 ObjectAddressExtra *thisextra = targetObjects->extras + i;
00436
00437 if (thisextra->flags & DEPFLAG_ORIGINAL)
00438 continue;
00439
00440
00441
00442
00443
00444
00445
00446
00447 deleteOneObject(thisobj, &depRel, PERFORM_DELETION_INTERNAL);
00448 }
00449
00450
00451 free_object_addresses(targetObjects);
00452
00453 heap_close(depRel, RowExclusiveLock);
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 static void
00485 findDependentObjects(const ObjectAddress *object,
00486 int flags,
00487 ObjectAddressStack *stack,
00488 ObjectAddresses *targetObjects,
00489 const ObjectAddresses *pendingObjects,
00490 Relation *depRel)
00491 {
00492 ScanKeyData key[3];
00493 int nkeys;
00494 SysScanDesc scan;
00495 HeapTuple tup;
00496 ObjectAddress otherObject;
00497 ObjectAddressStack mystack;
00498 ObjectAddressExtra extra;
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 if (stack_address_present_add_flags(object, flags, stack))
00517 return;
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 if (object_address_present_add_flags(object, flags, targetObjects))
00529 return;
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 ScanKeyInit(&key[0],
00542 Anum_pg_depend_classid,
00543 BTEqualStrategyNumber, F_OIDEQ,
00544 ObjectIdGetDatum(object->classId));
00545 ScanKeyInit(&key[1],
00546 Anum_pg_depend_objid,
00547 BTEqualStrategyNumber, F_OIDEQ,
00548 ObjectIdGetDatum(object->objectId));
00549 if (object->objectSubId != 0)
00550 {
00551 ScanKeyInit(&key[2],
00552 Anum_pg_depend_objsubid,
00553 BTEqualStrategyNumber, F_INT4EQ,
00554 Int32GetDatum(object->objectSubId));
00555 nkeys = 3;
00556 }
00557 else
00558 nkeys = 2;
00559
00560 scan = systable_beginscan(*depRel, DependDependerIndexId, true,
00561 SnapshotNow, nkeys, key);
00562
00563 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00564 {
00565 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
00566
00567 otherObject.classId = foundDep->refclassid;
00568 otherObject.objectId = foundDep->refobjid;
00569 otherObject.objectSubId = foundDep->refobjsubid;
00570
00571 switch (foundDep->deptype)
00572 {
00573 case DEPENDENCY_NORMAL:
00574 case DEPENDENCY_AUTO:
00575
00576 break;
00577 case DEPENDENCY_INTERNAL:
00578 case DEPENDENCY_EXTENSION:
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 if (stack == NULL)
00591 {
00592 char *otherObjDesc;
00593
00594
00595
00596
00597
00598
00599
00600 if (pendingObjects &&
00601 object_address_present(&otherObject, pendingObjects))
00602 {
00603 systable_endscan(scan);
00604
00605 ReleaseDeletionLock(object);
00606 return;
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 if (creating_extension &&
00618 otherObject.classId == ExtensionRelationId &&
00619 otherObject.objectId == CurrentExtensionObject)
00620 break;
00621
00622
00623 otherObjDesc = getObjectDescription(&otherObject);
00624 ereport(ERROR,
00625 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00626 errmsg("cannot drop %s because %s requires it",
00627 getObjectDescription(object),
00628 otherObjDesc),
00629 errhint("You can drop %s instead.",
00630 otherObjDesc)));
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 if (stack_address_present_add_flags(&otherObject, 0, stack))
00642 break;
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 ReleaseDeletionLock(object);
00655 AcquireDeletionLock(&otherObject, 0);
00656
00657
00658
00659
00660
00661
00662
00663 if (!systable_recheck_tuple(scan, tup))
00664 {
00665 systable_endscan(scan);
00666 ReleaseDeletionLock(&otherObject);
00667 return;
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 findDependentObjects(&otherObject,
00682 DEPFLAG_REVERSE,
00683 stack,
00684 targetObjects,
00685 pendingObjects,
00686 depRel);
00687
00688 systable_endscan(scan);
00689 return;
00690 case DEPENDENCY_PIN:
00691
00692
00693
00694
00695
00696 elog(ERROR, "incorrect use of PIN dependency with %s",
00697 getObjectDescription(object));
00698 break;
00699 default:
00700 elog(ERROR, "unrecognized dependency type '%c' for %s",
00701 foundDep->deptype, getObjectDescription(object));
00702 break;
00703 }
00704 }
00705
00706 systable_endscan(scan);
00707
00708
00709
00710
00711
00712 mystack.object = object;
00713 mystack.flags = flags;
00714 mystack.next = stack;
00715
00716 ScanKeyInit(&key[0],
00717 Anum_pg_depend_refclassid,
00718 BTEqualStrategyNumber, F_OIDEQ,
00719 ObjectIdGetDatum(object->classId));
00720 ScanKeyInit(&key[1],
00721 Anum_pg_depend_refobjid,
00722 BTEqualStrategyNumber, F_OIDEQ,
00723 ObjectIdGetDatum(object->objectId));
00724 if (object->objectSubId != 0)
00725 {
00726 ScanKeyInit(&key[2],
00727 Anum_pg_depend_refobjsubid,
00728 BTEqualStrategyNumber, F_INT4EQ,
00729 Int32GetDatum(object->objectSubId));
00730 nkeys = 3;
00731 }
00732 else
00733 nkeys = 2;
00734
00735 scan = systable_beginscan(*depRel, DependReferenceIndexId, true,
00736 SnapshotNow, nkeys, key);
00737
00738 while (HeapTupleIsValid(tup = systable_getnext(scan)))
00739 {
00740 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
00741 int subflags;
00742
00743 otherObject.classId = foundDep->classid;
00744 otherObject.objectId = foundDep->objid;
00745 otherObject.objectSubId = foundDep->objsubid;
00746
00747
00748
00749
00750 AcquireDeletionLock(&otherObject, 0);
00751
00752
00753
00754
00755
00756
00757
00758
00759 if (!systable_recheck_tuple(scan, tup))
00760 {
00761
00762 ReleaseDeletionLock(&otherObject);
00763
00764 continue;
00765 }
00766
00767
00768 switch (foundDep->deptype)
00769 {
00770 case DEPENDENCY_NORMAL:
00771 subflags = DEPFLAG_NORMAL;
00772 break;
00773 case DEPENDENCY_AUTO:
00774 subflags = DEPFLAG_AUTO;
00775 break;
00776 case DEPENDENCY_INTERNAL:
00777 subflags = DEPFLAG_INTERNAL;
00778 break;
00779 case DEPENDENCY_EXTENSION:
00780 subflags = DEPFLAG_EXTENSION;
00781 break;
00782 case DEPENDENCY_PIN:
00783
00784
00785
00786
00787
00788 ereport(ERROR,
00789 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00790 errmsg("cannot drop %s because it is required by the database system",
00791 getObjectDescription(object))));
00792 subflags = 0;
00793 break;
00794 default:
00795 elog(ERROR, "unrecognized dependency type '%c' for %s",
00796 foundDep->deptype, getObjectDescription(object));
00797 subflags = 0;
00798 break;
00799 }
00800
00801 findDependentObjects(&otherObject,
00802 subflags,
00803 &mystack,
00804 targetObjects,
00805 pendingObjects,
00806 depRel);
00807 }
00808
00809 systable_endscan(scan);
00810
00811
00812
00813
00814
00815
00816 extra.flags = mystack.flags;
00817 if (stack)
00818 extra.dependee = *stack->object;
00819 else
00820 memset(&extra.dependee, 0, sizeof(extra.dependee));
00821 add_exact_object_address_extra(object, &extra, targetObjects);
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 static void
00838 reportDependentObjects(const ObjectAddresses *targetObjects,
00839 DropBehavior behavior,
00840 int msglevel,
00841 const ObjectAddress *origObject)
00842 {
00843 bool ok = true;
00844 StringInfoData clientdetail;
00845 StringInfoData logdetail;
00846 int numReportedClient = 0;
00847 int numNotReportedClient = 0;
00848 int i;
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 if (behavior == DROP_CASCADE &&
00860 msglevel < client_min_messages &&
00861 (msglevel < log_min_messages || log_min_messages == LOG))
00862 return;
00863
00864
00865
00866
00867
00868
00869 #define MAX_REPORTED_DEPS 100
00870
00871 initStringInfo(&clientdetail);
00872 initStringInfo(&logdetail);
00873
00874
00875
00876
00877
00878 for (i = targetObjects->numrefs - 1; i >= 0; i--)
00879 {
00880 const ObjectAddress *obj = &targetObjects->refs[i];
00881 const ObjectAddressExtra *extra = &targetObjects->extras[i];
00882 char *objDesc;
00883
00884
00885 if (extra->flags & DEPFLAG_ORIGINAL)
00886 continue;
00887
00888 objDesc = getObjectDescription(obj);
00889
00890
00891
00892
00893
00894
00895 if (extra->flags & (DEPFLAG_AUTO |
00896 DEPFLAG_INTERNAL |
00897 DEPFLAG_EXTENSION))
00898 {
00899
00900
00901
00902
00903
00904
00905 ereport(DEBUG2,
00906 (errmsg("drop auto-cascades to %s",
00907 objDesc)));
00908 }
00909 else if (behavior == DROP_RESTRICT)
00910 {
00911 char *otherDesc = getObjectDescription(&extra->dependee);
00912
00913 if (numReportedClient < MAX_REPORTED_DEPS)
00914 {
00915
00916 if (clientdetail.len != 0)
00917 appendStringInfoChar(&clientdetail, '\n');
00918 appendStringInfo(&clientdetail, _("%s depends on %s"),
00919 objDesc, otherDesc);
00920 numReportedClient++;
00921 }
00922 else
00923 numNotReportedClient++;
00924
00925 if (logdetail.len != 0)
00926 appendStringInfoChar(&logdetail, '\n');
00927 appendStringInfo(&logdetail, _("%s depends on %s"),
00928 objDesc, otherDesc);
00929 pfree(otherDesc);
00930 ok = false;
00931 }
00932 else
00933 {
00934 if (numReportedClient < MAX_REPORTED_DEPS)
00935 {
00936
00937 if (clientdetail.len != 0)
00938 appendStringInfoChar(&clientdetail, '\n');
00939 appendStringInfo(&clientdetail, _("drop cascades to %s"),
00940 objDesc);
00941 numReportedClient++;
00942 }
00943 else
00944 numNotReportedClient++;
00945
00946 if (logdetail.len != 0)
00947 appendStringInfoChar(&logdetail, '\n');
00948 appendStringInfo(&logdetail, _("drop cascades to %s"),
00949 objDesc);
00950 }
00951
00952 pfree(objDesc);
00953 }
00954
00955 if (numNotReportedClient > 0)
00956 appendStringInfo(&clientdetail, ngettext("\nand %d other object "
00957 "(see server log for list)",
00958 "\nand %d other objects "
00959 "(see server log for list)",
00960 numNotReportedClient),
00961 numNotReportedClient);
00962
00963 if (!ok)
00964 {
00965 if (origObject)
00966 ereport(ERROR,
00967 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00968 errmsg("cannot drop %s because other objects depend on it",
00969 getObjectDescription(origObject)),
00970 errdetail("%s", clientdetail.data),
00971 errdetail_log("%s", logdetail.data),
00972 errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
00973 else
00974 ereport(ERROR,
00975 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
00976 errmsg("cannot drop desired object(s) because other objects depend on them"),
00977 errdetail("%s", clientdetail.data),
00978 errdetail_log("%s", logdetail.data),
00979 errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
00980 }
00981 else if (numReportedClient > 1)
00982 {
00983 ereport(msglevel,
00984
00985 (errmsg_plural("drop cascades to %d other object",
00986 "drop cascades to %d other objects",
00987 numReportedClient + numNotReportedClient,
00988 numReportedClient + numNotReportedClient),
00989 errdetail("%s", clientdetail.data),
00990 errdetail_log("%s", logdetail.data)));
00991 }
00992 else if (numReportedClient == 1)
00993 {
00994
00995 ereport(msglevel,
00996 (errmsg_internal("%s", clientdetail.data)));
00997 }
00998
00999 pfree(clientdetail.data);
01000 pfree(logdetail.data);
01001 }
01002
01003
01004
01005
01006
01007
01008 static void
01009 deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
01010 {
01011 ScanKeyData key[3];
01012 int nkeys;
01013 SysScanDesc scan;
01014 HeapTuple tup;
01015
01016
01017 InvokeObjectDropHookArg(object->classId, object->objectId,
01018 object->objectSubId, flags);
01019
01020
01021
01022
01023
01024
01025 if (flags & PERFORM_DELETION_CONCURRENTLY)
01026 heap_close(*depRel, RowExclusiveLock);
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 doDeletion(object, flags);
01038
01039
01040
01041
01042 if (flags & PERFORM_DELETION_CONCURRENTLY)
01043 *depRel = heap_open(DependRelationId, RowExclusiveLock);
01044
01045
01046
01047
01048
01049
01050
01051
01052 ScanKeyInit(&key[0],
01053 Anum_pg_depend_classid,
01054 BTEqualStrategyNumber, F_OIDEQ,
01055 ObjectIdGetDatum(object->classId));
01056 ScanKeyInit(&key[1],
01057 Anum_pg_depend_objid,
01058 BTEqualStrategyNumber, F_OIDEQ,
01059 ObjectIdGetDatum(object->objectId));
01060 if (object->objectSubId != 0)
01061 {
01062 ScanKeyInit(&key[2],
01063 Anum_pg_depend_objsubid,
01064 BTEqualStrategyNumber, F_INT4EQ,
01065 Int32GetDatum(object->objectSubId));
01066 nkeys = 3;
01067 }
01068 else
01069 nkeys = 2;
01070
01071 scan = systable_beginscan(*depRel, DependDependerIndexId, true,
01072 SnapshotNow, nkeys, key);
01073
01074 while (HeapTupleIsValid(tup = systable_getnext(scan)))
01075 {
01076 simple_heap_delete(*depRel, &tup->t_self);
01077 }
01078
01079 systable_endscan(scan);
01080
01081
01082
01083
01084
01085 deleteSharedDependencyRecordsFor(object->classId, object->objectId,
01086 object->objectSubId);
01087
01088
01089
01090
01091
01092
01093
01094 DeleteComments(object->objectId, object->classId, object->objectSubId);
01095 DeleteSecurityLabel(object);
01096
01097
01098
01099
01100
01101 CommandCounterIncrement();
01102
01103
01104
01105
01106 }
01107
01108
01109
01110
01111 static void
01112 doDeletion(const ObjectAddress *object, int flags)
01113 {
01114 switch (getObjectClass(object))
01115 {
01116 case OCLASS_CLASS:
01117 {
01118 char relKind = get_rel_relkind(object->objectId);
01119
01120 if (relKind == RELKIND_INDEX)
01121 {
01122 bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY)
01123 == PERFORM_DELETION_CONCURRENTLY);
01124
01125 Assert(object->objectSubId == 0);
01126 index_drop(object->objectId, concurrent);
01127 }
01128 else
01129 {
01130 if (object->objectSubId != 0)
01131 RemoveAttributeById(object->objectId,
01132 object->objectSubId);
01133 else
01134 heap_drop_with_catalog(object->objectId);
01135 }
01136 break;
01137 }
01138
01139 case OCLASS_PROC:
01140 RemoveFunctionById(object->objectId);
01141 break;
01142
01143 case OCLASS_TYPE:
01144 RemoveTypeById(object->objectId);
01145 break;
01146
01147 case OCLASS_CAST:
01148 DropCastById(object->objectId);
01149 break;
01150
01151 case OCLASS_COLLATION:
01152 RemoveCollationById(object->objectId);
01153 break;
01154
01155 case OCLASS_CONSTRAINT:
01156 RemoveConstraintById(object->objectId);
01157 break;
01158
01159 case OCLASS_CONVERSION:
01160 RemoveConversionById(object->objectId);
01161 break;
01162
01163 case OCLASS_DEFAULT:
01164 RemoveAttrDefaultById(object->objectId);
01165 break;
01166
01167 case OCLASS_LANGUAGE:
01168 DropProceduralLanguageById(object->objectId);
01169 break;
01170
01171 case OCLASS_LARGEOBJECT:
01172 LargeObjectDrop(object->objectId);
01173 break;
01174
01175 case OCLASS_OPERATOR:
01176 RemoveOperatorById(object->objectId);
01177 break;
01178
01179 case OCLASS_OPCLASS:
01180 RemoveOpClassById(object->objectId);
01181 break;
01182
01183 case OCLASS_OPFAMILY:
01184 RemoveOpFamilyById(object->objectId);
01185 break;
01186
01187 case OCLASS_AMOP:
01188 RemoveAmOpEntryById(object->objectId);
01189 break;
01190
01191 case OCLASS_AMPROC:
01192 RemoveAmProcEntryById(object->objectId);
01193 break;
01194
01195 case OCLASS_REWRITE:
01196 RemoveRewriteRuleById(object->objectId);
01197 break;
01198
01199 case OCLASS_TRIGGER:
01200 RemoveTriggerById(object->objectId);
01201 break;
01202
01203 case OCLASS_SCHEMA:
01204 RemoveSchemaById(object->objectId);
01205 break;
01206
01207 case OCLASS_TSPARSER:
01208 RemoveTSParserById(object->objectId);
01209 break;
01210
01211 case OCLASS_TSDICT:
01212 RemoveTSDictionaryById(object->objectId);
01213 break;
01214
01215 case OCLASS_TSTEMPLATE:
01216 RemoveTSTemplateById(object->objectId);
01217 break;
01218
01219 case OCLASS_TSCONFIG:
01220 RemoveTSConfigurationById(object->objectId);
01221 break;
01222
01223
01224
01225
01226
01227
01228 case OCLASS_FDW:
01229 RemoveForeignDataWrapperById(object->objectId);
01230 break;
01231
01232 case OCLASS_FOREIGN_SERVER:
01233 RemoveForeignServerById(object->objectId);
01234 break;
01235
01236 case OCLASS_USER_MAPPING:
01237 RemoveUserMappingById(object->objectId);
01238 break;
01239
01240 case OCLASS_DEFACL:
01241 RemoveDefaultACLById(object->objectId);
01242 break;
01243
01244 case OCLASS_EXTENSION:
01245 RemoveExtensionById(object->objectId);
01246 break;
01247
01248 case OCLASS_EVENT_TRIGGER:
01249 RemoveEventTriggerById(object->objectId);
01250 break;
01251
01252 default:
01253 elog(ERROR, "unrecognized object class: %u",
01254 object->classId);
01255 }
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265 static void
01266 AcquireDeletionLock(const ObjectAddress *object, int flags)
01267 {
01268 if (object->classId == RelationRelationId)
01269 {
01270
01271
01272
01273
01274
01275
01276 if (flags & PERFORM_DELETION_CONCURRENTLY)
01277 LockRelationOid(object->objectId, ShareUpdateExclusiveLock);
01278 else
01279 LockRelationOid(object->objectId, AccessExclusiveLock);
01280 }
01281 else
01282 {
01283
01284 LockDatabaseObject(object->classId, object->objectId, 0,
01285 AccessExclusiveLock);
01286 }
01287 }
01288
01289
01290
01291
01292 static void
01293 ReleaseDeletionLock(const ObjectAddress *object)
01294 {
01295 if (object->classId == RelationRelationId)
01296 UnlockRelationOid(object->objectId, AccessExclusiveLock);
01297 else
01298
01299 UnlockDatabaseObject(object->classId, object->objectId, 0,
01300 AccessExclusiveLock);
01301 }
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 void
01318 recordDependencyOnExpr(const ObjectAddress *depender,
01319 Node *expr, List *rtable,
01320 DependencyType behavior)
01321 {
01322 find_expr_references_context context;
01323
01324 context.addrs = new_object_addresses();
01325
01326
01327 context.rtables = list_make1(rtable);
01328
01329
01330 find_expr_references_walker(expr, &context);
01331
01332
01333 eliminate_duplicate_dependencies(context.addrs);
01334
01335
01336 recordMultipleDependencies(depender,
01337 context.addrs->refs, context.addrs->numrefs,
01338 behavior);
01339
01340 free_object_addresses(context.addrs);
01341 }
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 void
01359 recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
01360 Node *expr, Oid relId,
01361 DependencyType behavior,
01362 DependencyType self_behavior)
01363 {
01364 find_expr_references_context context;
01365 RangeTblEntry rte;
01366
01367 context.addrs = new_object_addresses();
01368
01369
01370 MemSet(&rte, 0, sizeof(rte));
01371 rte.type = T_RangeTblEntry;
01372 rte.rtekind = RTE_RELATION;
01373 rte.relid = relId;
01374 rte.relkind = RELKIND_RELATION;
01375
01376 context.rtables = list_make1(list_make1(&rte));
01377
01378
01379 find_expr_references_walker(expr, &context);
01380
01381
01382 eliminate_duplicate_dependencies(context.addrs);
01383
01384
01385 if (behavior != self_behavior && context.addrs->numrefs > 0)
01386 {
01387 ObjectAddresses *self_addrs;
01388 ObjectAddress *outobj;
01389 int oldref,
01390 outrefs;
01391
01392 self_addrs = new_object_addresses();
01393
01394 outobj = context.addrs->refs;
01395 outrefs = 0;
01396 for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
01397 {
01398 ObjectAddress *thisobj = context.addrs->refs + oldref;
01399
01400 if (thisobj->classId == RelationRelationId &&
01401 thisobj->objectId == relId)
01402 {
01403
01404 add_exact_object_address(thisobj, self_addrs);
01405 }
01406 else
01407 {
01408
01409 *outobj = *thisobj;
01410 outobj++;
01411 outrefs++;
01412 }
01413 }
01414 context.addrs->numrefs = outrefs;
01415
01416
01417 recordMultipleDependencies(depender,
01418 self_addrs->refs, self_addrs->numrefs,
01419 self_behavior);
01420
01421 free_object_addresses(self_addrs);
01422 }
01423
01424
01425 recordMultipleDependencies(depender,
01426 context.addrs->refs, context.addrs->numrefs,
01427 behavior);
01428
01429 free_object_addresses(context.addrs);
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 static bool
01452 find_expr_references_walker(Node *node,
01453 find_expr_references_context *context)
01454 {
01455 if (node == NULL)
01456 return false;
01457 if (IsA(node, Var))
01458 {
01459 Var *var = (Var *) node;
01460 List *rtable;
01461 RangeTblEntry *rte;
01462
01463
01464 if (var->varlevelsup >= list_length(context->rtables))
01465 elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
01466 rtable = (List *) list_nth(context->rtables, var->varlevelsup);
01467 if (var->varno <= 0 || var->varno > list_length(rtable))
01468 elog(ERROR, "invalid varno %d", var->varno);
01469 rte = rt_fetch(var->varno, rtable);
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482 if (var->varattno == InvalidAttrNumber)
01483 return false;
01484 if (rte->rtekind == RTE_RELATION)
01485 {
01486
01487 add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
01488 context->addrs);
01489 }
01490 else if (rte->rtekind == RTE_JOIN)
01491 {
01492
01493 List *save_rtables;
01494
01495
01496 save_rtables = context->rtables;
01497 context->rtables = list_copy_tail(context->rtables,
01498 var->varlevelsup);
01499 if (var->varattno <= 0 ||
01500 var->varattno > list_length(rte->joinaliasvars))
01501 elog(ERROR, "invalid varattno %d", var->varattno);
01502 find_expr_references_walker((Node *) list_nth(rte->joinaliasvars,
01503 var->varattno - 1),
01504 context);
01505 list_free(context->rtables);
01506 context->rtables = save_rtables;
01507 }
01508 return false;
01509 }
01510 else if (IsA(node, Const))
01511 {
01512 Const *con = (Const *) node;
01513 Oid objoid;
01514
01515
01516 add_object_address(OCLASS_TYPE, con->consttype, 0,
01517 context->addrs);
01518
01519
01520
01521
01522
01523
01524
01525 if (OidIsValid(con->constcollid) &&
01526 con->constcollid != DEFAULT_COLLATION_OID)
01527 add_object_address(OCLASS_COLLATION, con->constcollid, 0,
01528 context->addrs);
01529
01530
01531
01532
01533
01534
01535
01536 if (!con->constisnull)
01537 {
01538 switch (con->consttype)
01539 {
01540 case REGPROCOID:
01541 case REGPROCEDUREOID:
01542 objoid = DatumGetObjectId(con->constvalue);
01543 if (SearchSysCacheExists1(PROCOID,
01544 ObjectIdGetDatum(objoid)))
01545 add_object_address(OCLASS_PROC, objoid, 0,
01546 context->addrs);
01547 break;
01548 case REGOPEROID:
01549 case REGOPERATOROID:
01550 objoid = DatumGetObjectId(con->constvalue);
01551 if (SearchSysCacheExists1(OPEROID,
01552 ObjectIdGetDatum(objoid)))
01553 add_object_address(OCLASS_OPERATOR, objoid, 0,
01554 context->addrs);
01555 break;
01556 case REGCLASSOID:
01557 objoid = DatumGetObjectId(con->constvalue);
01558 if (SearchSysCacheExists1(RELOID,
01559 ObjectIdGetDatum(objoid)))
01560 add_object_address(OCLASS_CLASS, objoid, 0,
01561 context->addrs);
01562 break;
01563 case REGTYPEOID:
01564 objoid = DatumGetObjectId(con->constvalue);
01565 if (SearchSysCacheExists1(TYPEOID,
01566 ObjectIdGetDatum(objoid)))
01567 add_object_address(OCLASS_TYPE, objoid, 0,
01568 context->addrs);
01569 break;
01570 case REGCONFIGOID:
01571 objoid = DatumGetObjectId(con->constvalue);
01572 if (SearchSysCacheExists1(TSCONFIGOID,
01573 ObjectIdGetDatum(objoid)))
01574 add_object_address(OCLASS_TSCONFIG, objoid, 0,
01575 context->addrs);
01576 break;
01577 case REGDICTIONARYOID:
01578 objoid = DatumGetObjectId(con->constvalue);
01579 if (SearchSysCacheExists1(TSDICTOID,
01580 ObjectIdGetDatum(objoid)))
01581 add_object_address(OCLASS_TSDICT, objoid, 0,
01582 context->addrs);
01583 break;
01584 }
01585 }
01586 return false;
01587 }
01588 else if (IsA(node, Param))
01589 {
01590 Param *param = (Param *) node;
01591
01592
01593 add_object_address(OCLASS_TYPE, param->paramtype, 0,
01594 context->addrs);
01595
01596 if (OidIsValid(param->paramcollid) &&
01597 param->paramcollid != DEFAULT_COLLATION_OID)
01598 add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
01599 context->addrs);
01600 }
01601 else if (IsA(node, FuncExpr))
01602 {
01603 FuncExpr *funcexpr = (FuncExpr *) node;
01604
01605 add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
01606 context->addrs);
01607
01608 }
01609 else if (IsA(node, OpExpr))
01610 {
01611 OpExpr *opexpr = (OpExpr *) node;
01612
01613 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
01614 context->addrs);
01615
01616 }
01617 else if (IsA(node, DistinctExpr))
01618 {
01619 DistinctExpr *distinctexpr = (DistinctExpr *) node;
01620
01621 add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
01622 context->addrs);
01623
01624 }
01625 else if (IsA(node, NullIfExpr))
01626 {
01627 NullIfExpr *nullifexpr = (NullIfExpr *) node;
01628
01629 add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
01630 context->addrs);
01631
01632 }
01633 else if (IsA(node, ScalarArrayOpExpr))
01634 {
01635 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
01636
01637 add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
01638 context->addrs);
01639
01640 }
01641 else if (IsA(node, Aggref))
01642 {
01643 Aggref *aggref = (Aggref *) node;
01644
01645 add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
01646 context->addrs);
01647
01648 }
01649 else if (IsA(node, WindowFunc))
01650 {
01651 WindowFunc *wfunc = (WindowFunc *) node;
01652
01653 add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
01654 context->addrs);
01655
01656 }
01657 else if (IsA(node, SubPlan))
01658 {
01659
01660 elog(ERROR, "already-planned subqueries not supported");
01661 }
01662 else if (IsA(node, RelabelType))
01663 {
01664 RelabelType *relab = (RelabelType *) node;
01665
01666
01667 add_object_address(OCLASS_TYPE, relab->resulttype, 0,
01668 context->addrs);
01669
01670 if (OidIsValid(relab->resultcollid) &&
01671 relab->resultcollid != DEFAULT_COLLATION_OID)
01672 add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
01673 context->addrs);
01674 }
01675 else if (IsA(node, CoerceViaIO))
01676 {
01677 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
01678
01679
01680 add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
01681 context->addrs);
01682 }
01683 else if (IsA(node, ArrayCoerceExpr))
01684 {
01685 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
01686
01687 if (OidIsValid(acoerce->elemfuncid))
01688 add_object_address(OCLASS_PROC, acoerce->elemfuncid, 0,
01689 context->addrs);
01690 add_object_address(OCLASS_TYPE, acoerce->resulttype, 0,
01691 context->addrs);
01692
01693 }
01694 else if (IsA(node, ConvertRowtypeExpr))
01695 {
01696 ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
01697
01698
01699 add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
01700 context->addrs);
01701 }
01702 else if (IsA(node, CollateExpr))
01703 {
01704 CollateExpr *coll = (CollateExpr *) node;
01705
01706 add_object_address(OCLASS_COLLATION, coll->collOid, 0,
01707 context->addrs);
01708 }
01709 else if (IsA(node, RowExpr))
01710 {
01711 RowExpr *rowexpr = (RowExpr *) node;
01712
01713 add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
01714 context->addrs);
01715 }
01716 else if (IsA(node, RowCompareExpr))
01717 {
01718 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
01719 ListCell *l;
01720
01721 foreach(l, rcexpr->opnos)
01722 {
01723 add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
01724 context->addrs);
01725 }
01726 foreach(l, rcexpr->opfamilies)
01727 {
01728 add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
01729 context->addrs);
01730 }
01731
01732 }
01733 else if (IsA(node, CoerceToDomain))
01734 {
01735 CoerceToDomain *cd = (CoerceToDomain *) node;
01736
01737 add_object_address(OCLASS_TYPE, cd->resulttype, 0,
01738 context->addrs);
01739 }
01740 else if (IsA(node, SortGroupClause))
01741 {
01742 SortGroupClause *sgc = (SortGroupClause *) node;
01743
01744 add_object_address(OCLASS_OPERATOR, sgc->eqop, 0,
01745 context->addrs);
01746 if (OidIsValid(sgc->sortop))
01747 add_object_address(OCLASS_OPERATOR, sgc->sortop, 0,
01748 context->addrs);
01749 return false;
01750 }
01751 else if (IsA(node, Query))
01752 {
01753
01754 Query *query = (Query *) node;
01755 ListCell *lc;
01756 bool result;
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 foreach(lc, query->rtable)
01772 {
01773 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
01774 ListCell *ct;
01775
01776 switch (rte->rtekind)
01777 {
01778 case RTE_RELATION:
01779 add_object_address(OCLASS_CLASS, rte->relid, 0,
01780 context->addrs);
01781 break;
01782 case RTE_FUNCTION:
01783 foreach(ct, rte->funccoltypes)
01784 {
01785 add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
01786 context->addrs);
01787 }
01788 foreach(ct, rte->funccolcollations)
01789 {
01790 Oid collid = lfirst_oid(ct);
01791
01792 if (OidIsValid(collid) &&
01793 collid != DEFAULT_COLLATION_OID)
01794 add_object_address(OCLASS_COLLATION, collid, 0,
01795 context->addrs);
01796 }
01797 break;
01798 default:
01799 break;
01800 }
01801 }
01802
01803
01804
01805
01806
01807
01808
01809
01810 if (query->commandType == CMD_INSERT ||
01811 query->commandType == CMD_UPDATE)
01812 {
01813 RangeTblEntry *rte;
01814
01815 if (query->resultRelation <= 0 ||
01816 query->resultRelation > list_length(query->rtable))
01817 elog(ERROR, "invalid resultRelation %d",
01818 query->resultRelation);
01819 rte = rt_fetch(query->resultRelation, query->rtable);
01820 if (rte->rtekind == RTE_RELATION)
01821 {
01822 foreach(lc, query->targetList)
01823 {
01824 TargetEntry *tle = (TargetEntry *) lfirst(lc);
01825
01826 if (tle->resjunk)
01827 continue;
01828 add_object_address(OCLASS_CLASS, rte->relid, tle->resno,
01829 context->addrs);
01830 }
01831 }
01832 }
01833
01834
01835
01836
01837 foreach(lc, query->constraintDeps)
01838 {
01839 add_object_address(OCLASS_CONSTRAINT, lfirst_oid(lc), 0,
01840 context->addrs);
01841 }
01842
01843
01844 find_expr_references_walker((Node *) query->sortClause, context);
01845 find_expr_references_walker((Node *) query->groupClause, context);
01846 find_expr_references_walker((Node *) query->windowClause, context);
01847 find_expr_references_walker((Node *) query->distinctClause, context);
01848
01849
01850 context->rtables = lcons(query->rtable, context->rtables);
01851 result = query_tree_walker(query,
01852 find_expr_references_walker,
01853 (void *) context,
01854 QTW_IGNORE_JOINALIASES);
01855 context->rtables = list_delete_first(context->rtables);
01856 return result;
01857 }
01858 else if (IsA(node, SetOperationStmt))
01859 {
01860 SetOperationStmt *setop = (SetOperationStmt *) node;
01861
01862
01863 find_expr_references_walker((Node *) setop->groupClauses, context);
01864
01865 }
01866
01867 return expression_tree_walker(node, find_expr_references_walker,
01868 (void *) context);
01869 }
01870
01871
01872
01873
01874 static void
01875 eliminate_duplicate_dependencies(ObjectAddresses *addrs)
01876 {
01877 ObjectAddress *priorobj;
01878 int oldref,
01879 newrefs;
01880
01881
01882
01883
01884
01885
01886 Assert(!addrs->extras);
01887
01888 if (addrs->numrefs <= 1)
01889 return;
01890
01891
01892 qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
01893 object_address_comparator);
01894
01895
01896 priorobj = addrs->refs;
01897 newrefs = 1;
01898 for (oldref = 1; oldref < addrs->numrefs; oldref++)
01899 {
01900 ObjectAddress *thisobj = addrs->refs + oldref;
01901
01902 if (priorobj->classId == thisobj->classId &&
01903 priorobj->objectId == thisobj->objectId)
01904 {
01905 if (priorobj->objectSubId == thisobj->objectSubId)
01906 continue;
01907
01908
01909
01910
01911
01912
01913
01914
01915 if (priorobj->objectSubId == 0)
01916 {
01917
01918 priorobj->objectSubId = thisobj->objectSubId;
01919 continue;
01920 }
01921 }
01922
01923 priorobj++;
01924 *priorobj = *thisobj;
01925 newrefs++;
01926 }
01927
01928 addrs->numrefs = newrefs;
01929 }
01930
01931
01932
01933
01934 static int
01935 object_address_comparator(const void *a, const void *b)
01936 {
01937 const ObjectAddress *obja = (const ObjectAddress *) a;
01938 const ObjectAddress *objb = (const ObjectAddress *) b;
01939
01940 if (obja->classId < objb->classId)
01941 return -1;
01942 if (obja->classId > objb->classId)
01943 return 1;
01944 if (obja->objectId < objb->objectId)
01945 return -1;
01946 if (obja->objectId > objb->objectId)
01947 return 1;
01948
01949
01950
01951
01952
01953 if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
01954 return -1;
01955 if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
01956 return 1;
01957 return 0;
01958 }
01959
01960
01961
01962
01963
01964
01965 ObjectAddresses *
01966 new_object_addresses(void)
01967 {
01968 ObjectAddresses *addrs;
01969
01970 addrs = palloc(sizeof(ObjectAddresses));
01971
01972 addrs->numrefs = 0;
01973 addrs->maxrefs = 32;
01974 addrs->refs = (ObjectAddress *)
01975 palloc(addrs->maxrefs * sizeof(ObjectAddress));
01976 addrs->extras = NULL;
01977
01978 return addrs;
01979 }
01980
01981
01982
01983
01984
01985
01986
01987 static void
01988 add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
01989 ObjectAddresses *addrs)
01990 {
01991 ObjectAddress *item;
01992
01993
01994 if (addrs->numrefs >= addrs->maxrefs)
01995 {
01996 addrs->maxrefs *= 2;
01997 addrs->refs = (ObjectAddress *)
01998 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
01999 Assert(!addrs->extras);
02000 }
02001
02002 item = addrs->refs + addrs->numrefs;
02003 item->classId = object_classes[oclass];
02004 item->objectId = objectId;
02005 item->objectSubId = subId;
02006 addrs->numrefs++;
02007 }
02008
02009
02010
02011
02012
02013
02014 void
02015 add_exact_object_address(const ObjectAddress *object,
02016 ObjectAddresses *addrs)
02017 {
02018 ObjectAddress *item;
02019
02020
02021 if (addrs->numrefs >= addrs->maxrefs)
02022 {
02023 addrs->maxrefs *= 2;
02024 addrs->refs = (ObjectAddress *)
02025 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
02026 Assert(!addrs->extras);
02027 }
02028
02029 item = addrs->refs + addrs->numrefs;
02030 *item = *object;
02031 addrs->numrefs++;
02032 }
02033
02034
02035
02036
02037
02038
02039 static void
02040 add_exact_object_address_extra(const ObjectAddress *object,
02041 const ObjectAddressExtra *extra,
02042 ObjectAddresses *addrs)
02043 {
02044 ObjectAddress *item;
02045 ObjectAddressExtra *itemextra;
02046
02047
02048 if (!addrs->extras)
02049 addrs->extras = (ObjectAddressExtra *)
02050 palloc(addrs->maxrefs * sizeof(ObjectAddressExtra));
02051
02052
02053 if (addrs->numrefs >= addrs->maxrefs)
02054 {
02055 addrs->maxrefs *= 2;
02056 addrs->refs = (ObjectAddress *)
02057 repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
02058 addrs->extras = (ObjectAddressExtra *)
02059 repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
02060 }
02061
02062 item = addrs->refs + addrs->numrefs;
02063 *item = *object;
02064 itemextra = addrs->extras + addrs->numrefs;
02065 *itemextra = *extra;
02066 addrs->numrefs++;
02067 }
02068
02069
02070
02071
02072
02073
02074 bool
02075 object_address_present(const ObjectAddress *object,
02076 const ObjectAddresses *addrs)
02077 {
02078 int i;
02079
02080 for (i = addrs->numrefs - 1; i >= 0; i--)
02081 {
02082 const ObjectAddress *thisobj = addrs->refs + i;
02083
02084 if (object->classId == thisobj->classId &&
02085 object->objectId == thisobj->objectId)
02086 {
02087 if (object->objectSubId == thisobj->objectSubId ||
02088 thisobj->objectSubId == 0)
02089 return true;
02090 }
02091 }
02092
02093 return false;
02094 }
02095
02096
02097
02098
02099
02100 static bool
02101 object_address_present_add_flags(const ObjectAddress *object,
02102 int flags,
02103 ObjectAddresses *addrs)
02104 {
02105 int i;
02106
02107 for (i = addrs->numrefs - 1; i >= 0; i--)
02108 {
02109 ObjectAddress *thisobj = addrs->refs + i;
02110
02111 if (object->classId == thisobj->classId &&
02112 object->objectId == thisobj->objectId)
02113 {
02114 if (object->objectSubId == thisobj->objectSubId)
02115 {
02116 ObjectAddressExtra *thisextra = addrs->extras + i;
02117
02118 thisextra->flags |= flags;
02119 return true;
02120 }
02121 if (thisobj->objectSubId == 0)
02122 {
02123
02124
02125
02126
02127
02128
02129 return true;
02130 }
02131 }
02132 }
02133
02134 return false;
02135 }
02136
02137
02138
02139
02140 static bool
02141 stack_address_present_add_flags(const ObjectAddress *object,
02142 int flags,
02143 ObjectAddressStack *stack)
02144 {
02145 ObjectAddressStack *stackptr;
02146
02147 for (stackptr = stack; stackptr; stackptr = stackptr->next)
02148 {
02149 const ObjectAddress *thisobj = stackptr->object;
02150
02151 if (object->classId == thisobj->classId &&
02152 object->objectId == thisobj->objectId)
02153 {
02154 if (object->objectSubId == thisobj->objectSubId)
02155 {
02156 stackptr->flags |= flags;
02157 return true;
02158 }
02159
02160
02161
02162
02163
02164
02165
02166 if (thisobj->objectSubId == 0)
02167 return true;
02168 }
02169 }
02170
02171 return false;
02172 }
02173
02174
02175
02176
02177
02178 void
02179 record_object_address_dependencies(const ObjectAddress *depender,
02180 ObjectAddresses *referenced,
02181 DependencyType behavior)
02182 {
02183 eliminate_duplicate_dependencies(referenced);
02184 recordMultipleDependencies(depender,
02185 referenced->refs, referenced->numrefs,
02186 behavior);
02187 }
02188
02189
02190
02191
02192 void
02193 free_object_addresses(ObjectAddresses *addrs)
02194 {
02195 pfree(addrs->refs);
02196 if (addrs->extras)
02197 pfree(addrs->extras);
02198 pfree(addrs);
02199 }
02200
02201
02202
02203
02204
02205
02206
02207 ObjectClass
02208 getObjectClass(const ObjectAddress *object)
02209 {
02210
02211 if (object->classId != RelationRelationId &&
02212 object->objectSubId != 0)
02213 elog(ERROR, "invalid non-zero objectSubId for object class %u",
02214 object->classId);
02215
02216 switch (object->classId)
02217 {
02218 case RelationRelationId:
02219
02220 return OCLASS_CLASS;
02221
02222 case ProcedureRelationId:
02223 return OCLASS_PROC;
02224
02225 case TypeRelationId:
02226 return OCLASS_TYPE;
02227
02228 case CastRelationId:
02229 return OCLASS_CAST;
02230
02231 case CollationRelationId:
02232 return OCLASS_COLLATION;
02233
02234 case ConstraintRelationId:
02235 return OCLASS_CONSTRAINT;
02236
02237 case ConversionRelationId:
02238 return OCLASS_CONVERSION;
02239
02240 case AttrDefaultRelationId:
02241 return OCLASS_DEFAULT;
02242
02243 case LanguageRelationId:
02244 return OCLASS_LANGUAGE;
02245
02246 case LargeObjectRelationId:
02247 return OCLASS_LARGEOBJECT;
02248
02249 case OperatorRelationId:
02250 return OCLASS_OPERATOR;
02251
02252 case OperatorClassRelationId:
02253 return OCLASS_OPCLASS;
02254
02255 case OperatorFamilyRelationId:
02256 return OCLASS_OPFAMILY;
02257
02258 case AccessMethodOperatorRelationId:
02259 return OCLASS_AMOP;
02260
02261 case AccessMethodProcedureRelationId:
02262 return OCLASS_AMPROC;
02263
02264 case RewriteRelationId:
02265 return OCLASS_REWRITE;
02266
02267 case TriggerRelationId:
02268 return OCLASS_TRIGGER;
02269
02270 case NamespaceRelationId:
02271 return OCLASS_SCHEMA;
02272
02273 case TSParserRelationId:
02274 return OCLASS_TSPARSER;
02275
02276 case TSDictionaryRelationId:
02277 return OCLASS_TSDICT;
02278
02279 case TSTemplateRelationId:
02280 return OCLASS_TSTEMPLATE;
02281
02282 case TSConfigRelationId:
02283 return OCLASS_TSCONFIG;
02284
02285 case AuthIdRelationId:
02286 return OCLASS_ROLE;
02287
02288 case DatabaseRelationId:
02289 return OCLASS_DATABASE;
02290
02291 case TableSpaceRelationId:
02292 return OCLASS_TBLSPACE;
02293
02294 case ForeignDataWrapperRelationId:
02295 return OCLASS_FDW;
02296
02297 case ForeignServerRelationId:
02298 return OCLASS_FOREIGN_SERVER;
02299
02300 case UserMappingRelationId:
02301 return OCLASS_USER_MAPPING;
02302
02303 case DefaultAclRelationId:
02304 return OCLASS_DEFACL;
02305
02306 case ExtensionRelationId:
02307 return OCLASS_EXTENSION;
02308
02309 case EventTriggerRelationId:
02310 return OCLASS_EVENT_TRIGGER;
02311 }
02312
02313
02314 elog(ERROR, "unrecognized object class: %u", object->classId);
02315 return OCLASS_CLASS;
02316 }