00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "pg_backup_archiver.h"
00017 #include "pg_backup_utils.h"
00018 #include "parallel.h"
00019
00020
00021 static const char *modulename = gettext_noop("sorter");
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 static const int oldObjectTypePriority[] =
00038 {
00039 1,
00040 1,
00041 2,
00042 2,
00043 2,
00044 3,
00045 3,
00046 4,
00047 4,
00048 4,
00049 5,
00050 6,
00051 8,
00052 15,
00053 16,
00054 17,
00055 14,
00056 18,
00057 2,
00058 2,
00059 11,
00060 7,
00061 4,
00062 4,
00063 4,
00064 4,
00065 4,
00066 4,
00067 19,
00068 9,
00069 12,
00070 10,
00071 13,
00072 20,
00073 15
00074 };
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static const int newObjectTypePriority[] =
00086 {
00087 1,
00088 4,
00089 5,
00090 5,
00091 6,
00092 7,
00093 8,
00094 9,
00095 9,
00096 3,
00097 11,
00098 18,
00099 20,
00100 27,
00101 28,
00102 29,
00103 26,
00104 30,
00105 2,
00106 10,
00107 23,
00108 19,
00109 12,
00110 14,
00111 13,
00112 15,
00113 16,
00114 17,
00115 31,
00116 21,
00117 24,
00118 22,
00119 25,
00120 32,
00121 33
00122 };
00123
00124 static DumpId preDataBoundId;
00125 static DumpId postDataBoundId;
00126
00127
00128 static int DOTypeNameCompare(const void *p1, const void *p2);
00129 static int DOTypeOidCompare(const void *p1, const void *p2);
00130 static bool TopoSort(DumpableObject **objs,
00131 int numObjs,
00132 DumpableObject **ordering,
00133 int *nOrdering);
00134 static void addHeapElement(int val, int *heap, int heapLength);
00135 static int removeHeapElement(int *heap, int heapLength);
00136 static void findDependencyLoops(DumpableObject **objs, int nObjs, int totObjs);
00137 static int findLoop(DumpableObject *obj,
00138 DumpId startPoint,
00139 bool *processed,
00140 DumpableObject **workspace,
00141 int depth);
00142 static void repairDependencyLoop(DumpableObject **loop,
00143 int nLoop);
00144 static void describeDumpableObject(DumpableObject *obj,
00145 char *buf, int bufsize);
00146
00147 static int DOSizeCompare(const void *p1, const void *p2);
00148
00149 static int
00150 findFirstEqualType(DumpableObjectType type, DumpableObject **objs, int numObjs)
00151 {
00152 int i;
00153
00154 for (i = 0; i < numObjs; i++)
00155 if (objs[i]->objType == type)
00156 return i;
00157 return -1;
00158 }
00159
00160 static int
00161 findFirstDifferentType(DumpableObjectType type, DumpableObject **objs, int numObjs, int start)
00162 {
00163 int i;
00164
00165 for (i = start; i < numObjs; i++)
00166 if (objs[i]->objType != type)
00167 return i;
00168 return numObjs - 1;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 void
00183 sortDataAndIndexObjectsBySize(DumpableObject **objs, int numObjs)
00184 {
00185 int startIdx,
00186 endIdx;
00187 void *startPtr;
00188
00189 if (numObjs <= 1)
00190 return;
00191
00192 startIdx = findFirstEqualType(DO_TABLE_DATA, objs, numObjs);
00193 if (startIdx >= 0)
00194 {
00195 endIdx = findFirstDifferentType(DO_TABLE_DATA, objs, numObjs, startIdx);
00196 startPtr = objs + startIdx;
00197 qsort(startPtr, endIdx - startIdx, sizeof(DumpableObject *),
00198 DOSizeCompare);
00199 }
00200
00201 startIdx = findFirstEqualType(DO_INDEX, objs, numObjs);
00202 if (startIdx >= 0)
00203 {
00204 endIdx = findFirstDifferentType(DO_INDEX, objs, numObjs, startIdx);
00205 startPtr = objs + startIdx;
00206 qsort(startPtr, endIdx - startIdx, sizeof(DumpableObject *),
00207 DOSizeCompare);
00208 }
00209 }
00210
00211 static int
00212 DOSizeCompare(const void *p1, const void *p2)
00213 {
00214 DumpableObject *obj1 = *(DumpableObject **) p1;
00215 DumpableObject *obj2 = *(DumpableObject **) p2;
00216 int obj1_size = 0;
00217 int obj2_size = 0;
00218
00219 if (obj1->objType == DO_TABLE_DATA)
00220 obj1_size = ((TableDataInfo *) obj1)->tdtable->relpages;
00221 if (obj1->objType == DO_INDEX)
00222 obj1_size = ((IndxInfo *) obj1)->relpages;
00223
00224 if (obj2->objType == DO_TABLE_DATA)
00225 obj2_size = ((TableDataInfo *) obj2)->tdtable->relpages;
00226 if (obj2->objType == DO_INDEX)
00227 obj2_size = ((IndxInfo *) obj2)->relpages;
00228
00229
00230 if (obj1_size > obj2_size)
00231 return -1;
00232 if (obj2_size > obj1_size)
00233 return 1;
00234
00235 return 0;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 void
00245 sortDumpableObjectsByTypeName(DumpableObject **objs, int numObjs)
00246 {
00247 if (numObjs > 1)
00248 qsort((void *) objs, numObjs, sizeof(DumpableObject *),
00249 DOTypeNameCompare);
00250 }
00251
00252 static int
00253 DOTypeNameCompare(const void *p1, const void *p2)
00254 {
00255 DumpableObject *obj1 = *(DumpableObject *const *) p1;
00256 DumpableObject *obj2 = *(DumpableObject *const *) p2;
00257 int cmpval;
00258
00259
00260 cmpval = newObjectTypePriority[obj1->objType] -
00261 newObjectTypePriority[obj2->objType];
00262
00263 if (cmpval != 0)
00264 return cmpval;
00265
00266
00267
00268
00269
00270
00271 if (obj1->namespace && obj2->namespace)
00272 {
00273 cmpval = strcmp(obj1->namespace->dobj.name,
00274 obj2->namespace->dobj.name);
00275 if (cmpval != 0)
00276 return cmpval;
00277 }
00278
00279
00280 cmpval = strcmp(obj1->name, obj2->name);
00281 if (cmpval != 0)
00282 return cmpval;
00283
00284
00285 if (obj1->objType == DO_FUNC || obj1->objType == DO_AGG)
00286 {
00287 FuncInfo *fobj1 = *(FuncInfo *const *) p1;
00288 FuncInfo *fobj2 = *(FuncInfo *const *) p2;
00289
00290 cmpval = fobj1->nargs - fobj2->nargs;
00291 if (cmpval != 0)
00292 return cmpval;
00293 cmpval = strcmp(fobj1->proiargs, fobj2->proiargs);
00294 if (cmpval != 0)
00295 return cmpval;
00296 }
00297 else if (obj1->objType == DO_OPERATOR)
00298 {
00299 OprInfo *oobj1 = *(OprInfo *const *) p1;
00300 OprInfo *oobj2 = *(OprInfo *const *) p2;
00301
00302
00303 cmpval = (oobj2->oprkind - oobj1->oprkind);
00304 if (cmpval != 0)
00305 return cmpval;
00306 }
00307 else if (obj1->objType == DO_ATTRDEF)
00308 {
00309 AttrDefInfo *adobj1 = *(AttrDefInfo *const *) p1;
00310 AttrDefInfo *adobj2 = *(AttrDefInfo *const *) p2;
00311
00312 cmpval = (adobj1->adnum - adobj2->adnum);
00313 if (cmpval != 0)
00314 return cmpval;
00315 }
00316
00317
00318 return oidcmp(obj1->catId.oid, obj2->catId.oid);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328 void
00329 sortDumpableObjectsByTypeOid(DumpableObject **objs, int numObjs)
00330 {
00331 if (numObjs > 1)
00332 qsort((void *) objs, numObjs, sizeof(DumpableObject *),
00333 DOTypeOidCompare);
00334 }
00335
00336 static int
00337 DOTypeOidCompare(const void *p1, const void *p2)
00338 {
00339 DumpableObject *obj1 = *(DumpableObject *const *) p1;
00340 DumpableObject *obj2 = *(DumpableObject *const *) p2;
00341 int cmpval;
00342
00343 cmpval = oldObjectTypePriority[obj1->objType] -
00344 oldObjectTypePriority[obj2->objType];
00345
00346 if (cmpval != 0)
00347 return cmpval;
00348
00349 return oidcmp(obj1->catId.oid, obj2->catId.oid);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 void
00361 sortDumpableObjects(DumpableObject **objs, int numObjs,
00362 DumpId preBoundaryId, DumpId postBoundaryId)
00363 {
00364 DumpableObject **ordering;
00365 int nOrdering;
00366
00367 if (numObjs <= 0)
00368 return;
00369
00370
00371
00372
00373
00374 preDataBoundId = preBoundaryId;
00375 postDataBoundId = postBoundaryId;
00376
00377 ordering = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *));
00378 while (!TopoSort(objs, numObjs, ordering, &nOrdering))
00379 findDependencyLoops(ordering, nOrdering, numObjs);
00380
00381 memcpy(objs, ordering, numObjs * sizeof(DumpableObject *));
00382
00383 free(ordering);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 static bool
00413 TopoSort(DumpableObject **objs,
00414 int numObjs,
00415 DumpableObject **ordering,
00416 int *nOrdering)
00417 {
00418 DumpId maxDumpId = getMaxDumpId();
00419 int *pendingHeap;
00420 int *beforeConstraints;
00421 int *idMap;
00422 DumpableObject *obj;
00423 int heapLength;
00424 int i,
00425 j,
00426 k;
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 *nOrdering = numObjs;
00442
00443
00444 if (numObjs <= 0)
00445 return true;
00446
00447
00448 pendingHeap = (int *) pg_malloc(numObjs * sizeof(int));
00449
00450
00451
00452
00453
00454
00455
00456
00457 beforeConstraints = (int *) pg_malloc((maxDumpId + 1) * sizeof(int));
00458 memset(beforeConstraints, 0, (maxDumpId + 1) * sizeof(int));
00459 idMap = (int *) pg_malloc((maxDumpId + 1) * sizeof(int));
00460 for (i = 0; i < numObjs; i++)
00461 {
00462 obj = objs[i];
00463 j = obj->dumpId;
00464 if (j <= 0 || j > maxDumpId)
00465 exit_horribly(modulename, "invalid dumpId %d\n", j);
00466 idMap[j] = i;
00467 for (j = 0; j < obj->nDeps; j++)
00468 {
00469 k = obj->dependencies[j];
00470 if (k <= 0 || k > maxDumpId)
00471 exit_horribly(modulename, "invalid dependency %d\n", k);
00472 beforeConstraints[k]++;
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 heapLength = 0;
00488 for (i = numObjs; --i >= 0;)
00489 {
00490 if (beforeConstraints[objs[i]->dumpId] == 0)
00491 pendingHeap[heapLength++] = i;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 i = numObjs;
00510 while (heapLength > 0)
00511 {
00512
00513 j = removeHeapElement(pendingHeap, heapLength--);
00514 obj = objs[j];
00515
00516 ordering[--i] = obj;
00517
00518 for (k = 0; k < obj->nDeps; k++)
00519 {
00520 int id = obj->dependencies[k];
00521
00522 if ((--beforeConstraints[id]) == 0)
00523 addHeapElement(idMap[id], pendingHeap, heapLength++);
00524 }
00525 }
00526
00527
00528
00529
00530
00531 if (i != 0)
00532 {
00533 k = 0;
00534 for (j = 1; j <= maxDumpId; j++)
00535 {
00536 if (beforeConstraints[j] != 0)
00537 ordering[k++] = objs[idMap[j]];
00538 }
00539 *nOrdering = k;
00540 }
00541
00542
00543 free(pendingHeap);
00544 free(beforeConstraints);
00545 free(idMap);
00546
00547 return (i == 0);
00548 }
00549
00550
00551
00552
00553
00554
00555
00556 static void
00557 addHeapElement(int val, int *heap, int heapLength)
00558 {
00559 int j;
00560
00561
00562
00563
00564
00565 j = heapLength;
00566 while (j > 0)
00567 {
00568 int i = (j - 1) >> 1;
00569
00570 if (val <= heap[i])
00571 break;
00572 heap[j] = heap[i];
00573 j = i;
00574 }
00575 heap[j] = val;
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 static int
00588 removeHeapElement(int *heap, int heapLength)
00589 {
00590 int result = heap[0];
00591 int val;
00592 int i;
00593
00594 if (--heapLength <= 0)
00595 return result;
00596 val = heap[heapLength];
00597 i = 0;
00598 for (;;)
00599 {
00600 int j = 2 * i + 1;
00601
00602 if (j >= heapLength)
00603 break;
00604 if (j + 1 < heapLength &&
00605 heap[j] < heap[j + 1])
00606 j++;
00607 if (val >= heap[j])
00608 break;
00609 heap[i] = heap[j];
00610 i = j;
00611 }
00612 heap[i] = val;
00613 return result;
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 static void
00633 findDependencyLoops(DumpableObject **objs, int nObjs, int totObjs)
00634 {
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 bool *processed;
00646 DumpableObject **workspace;
00647 bool fixedloop;
00648 int i;
00649
00650 processed = (bool *) pg_malloc0((getMaxDumpId() + 1) * sizeof(bool));
00651 workspace = (DumpableObject **) pg_malloc(totObjs * sizeof(DumpableObject *));
00652 fixedloop = false;
00653
00654 for (i = 0; i < nObjs; i++)
00655 {
00656 DumpableObject *obj = objs[i];
00657 int looplen;
00658 int j;
00659
00660 looplen = findLoop(obj, obj->dumpId, processed, workspace, 0);
00661
00662 if (looplen > 0)
00663 {
00664
00665 repairDependencyLoop(workspace, looplen);
00666 fixedloop = true;
00667
00668 for (j = 0; j < looplen; j++)
00669 processed[workspace[j]->dumpId] = true;
00670 }
00671 else
00672 {
00673
00674
00675
00676
00677
00678
00679 processed[obj->dumpId] = true;
00680 }
00681 }
00682
00683
00684 if (!fixedloop)
00685 exit_horribly(modulename, "could not identify dependency loop\n");
00686
00687 free(workspace);
00688 free(processed);
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 static int
00708 findLoop(DumpableObject *obj,
00709 DumpId startPoint,
00710 bool *processed,
00711 DumpableObject **workspace,
00712 int depth)
00713 {
00714 int i;
00715
00716
00717
00718
00719
00720 if (processed[obj->dumpId])
00721 return 0;
00722
00723
00724
00725
00726
00727
00728
00729 for (i = 0; i < depth; i++)
00730 {
00731 if (workspace[i] == obj)
00732 return 0;
00733 }
00734
00735
00736
00737
00738 workspace[depth++] = obj;
00739
00740
00741
00742
00743 for (i = 0; i < obj->nDeps; i++)
00744 {
00745 if (obj->dependencies[i] == startPoint)
00746 return depth;
00747 }
00748
00749
00750
00751
00752 for (i = 0; i < obj->nDeps; i++)
00753 {
00754 DumpableObject *nextobj = findObjectByDumpId(obj->dependencies[i]);
00755 int newDepth;
00756
00757 if (!nextobj)
00758 continue;
00759 newDepth = findLoop(nextobj,
00760 startPoint,
00761 processed,
00762 workspace,
00763 depth);
00764 if (newDepth > 0)
00765 return newDepth;
00766 }
00767
00768 return 0;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778 static void
00779 repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
00780 {
00781 TypeInfo *typeInfo = (TypeInfo *) typeobj;
00782
00783
00784 removeObjectDependency(funcobj, typeobj->dumpId);
00785
00786
00787 if (typeInfo->shellType)
00788 {
00789 addObjectDependency(funcobj, typeInfo->shellType->dobj.dumpId);
00790
00791 if (funcobj->dump)
00792 typeInfo->shellType->dobj.dump = true;
00793 }
00794 }
00795
00796
00797
00798
00799
00800
00801
00802 static void
00803 repairViewRuleLoop(DumpableObject *viewobj,
00804 DumpableObject *ruleobj)
00805 {
00806
00807 removeObjectDependency(ruleobj, viewobj->dumpId);
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 static void
00820 repairViewRuleMultiLoop(DumpableObject *viewobj,
00821 DumpableObject *ruleobj)
00822 {
00823 TableInfo *viewinfo = (TableInfo *) viewobj;
00824 RuleInfo *ruleinfo = (RuleInfo *) ruleobj;
00825
00826
00827 removeObjectDependency(viewobj, ruleobj->dumpId);
00828
00829 viewinfo->relkind = 'r';
00830
00831 ruleinfo->separate = true;
00832
00833 if (viewinfo->reloptions)
00834 {
00835 ruleinfo->reloptions = viewinfo->reloptions;
00836 viewinfo->reloptions = NULL;
00837 }
00838
00839 addObjectDependency(ruleobj, viewobj->dumpId);
00840
00841 addObjectDependency(ruleobj, postDataBoundId);
00842 }
00843
00844
00845
00846
00847
00848
00849
00850 static void
00851 repairTableConstraintLoop(DumpableObject *tableobj,
00852 DumpableObject *constraintobj)
00853 {
00854
00855 removeObjectDependency(constraintobj, tableobj->dumpId);
00856 }
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 static void
00868 repairTableConstraintMultiLoop(DumpableObject *tableobj,
00869 DumpableObject *constraintobj)
00870 {
00871
00872 removeObjectDependency(tableobj, constraintobj->dumpId);
00873
00874 ((ConstraintInfo *) constraintobj)->separate = true;
00875
00876 addObjectDependency(constraintobj, tableobj->dumpId);
00877
00878 addObjectDependency(constraintobj, postDataBoundId);
00879 }
00880
00881
00882
00883
00884 static void
00885 repairTableAttrDefLoop(DumpableObject *tableobj,
00886 DumpableObject *attrdefobj)
00887 {
00888
00889 removeObjectDependency(attrdefobj, tableobj->dumpId);
00890 }
00891
00892 static void
00893 repairTableAttrDefMultiLoop(DumpableObject *tableobj,
00894 DumpableObject *attrdefobj)
00895 {
00896
00897 removeObjectDependency(tableobj, attrdefobj->dumpId);
00898
00899 ((AttrDefInfo *) attrdefobj)->separate = true;
00900
00901 addObjectDependency(attrdefobj, tableobj->dumpId);
00902 }
00903
00904
00905
00906
00907 static void
00908 repairDomainConstraintLoop(DumpableObject *domainobj,
00909 DumpableObject *constraintobj)
00910 {
00911
00912 removeObjectDependency(constraintobj, domainobj->dumpId);
00913 }
00914
00915 static void
00916 repairDomainConstraintMultiLoop(DumpableObject *domainobj,
00917 DumpableObject *constraintobj)
00918 {
00919
00920 removeObjectDependency(domainobj, constraintobj->dumpId);
00921
00922 ((ConstraintInfo *) constraintobj)->separate = true;
00923
00924 addObjectDependency(constraintobj, domainobj->dumpId);
00925
00926 addObjectDependency(constraintobj, postDataBoundId);
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936 static void
00937 repairDependencyLoop(DumpableObject **loop,
00938 int nLoop)
00939 {
00940 int i,
00941 j;
00942
00943
00944 if (nLoop == 2 &&
00945 loop[0]->objType == DO_TYPE &&
00946 loop[1]->objType == DO_FUNC)
00947 {
00948 repairTypeFuncLoop(loop[0], loop[1]);
00949 return;
00950 }
00951 if (nLoop == 2 &&
00952 loop[1]->objType == DO_TYPE &&
00953 loop[0]->objType == DO_FUNC)
00954 {
00955 repairTypeFuncLoop(loop[1], loop[0]);
00956 return;
00957 }
00958
00959
00960 if (nLoop == 2 &&
00961 loop[0]->objType == DO_TABLE &&
00962 loop[1]->objType == DO_RULE &&
00963 ((RuleInfo *) loop[1])->ev_type == '1' &&
00964 ((RuleInfo *) loop[1])->is_instead &&
00965 ((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0])
00966 {
00967 repairViewRuleLoop(loop[0], loop[1]);
00968 return;
00969 }
00970 if (nLoop == 2 &&
00971 loop[1]->objType == DO_TABLE &&
00972 loop[0]->objType == DO_RULE &&
00973 ((RuleInfo *) loop[0])->ev_type == '1' &&
00974 ((RuleInfo *) loop[0])->is_instead &&
00975 ((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1])
00976 {
00977 repairViewRuleLoop(loop[1], loop[0]);
00978 return;
00979 }
00980
00981
00982 if (nLoop > 2)
00983 {
00984 for (i = 0; i < nLoop; i++)
00985 {
00986 if (loop[i]->objType == DO_TABLE)
00987 {
00988 for (j = 0; j < nLoop; j++)
00989 {
00990 if (loop[j]->objType == DO_RULE &&
00991 ((RuleInfo *) loop[j])->ev_type == '1' &&
00992 ((RuleInfo *) loop[j])->is_instead &&
00993 ((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i])
00994 {
00995 repairViewRuleMultiLoop(loop[i], loop[j]);
00996 return;
00997 }
00998 }
00999 }
01000 }
01001 }
01002
01003
01004 if (nLoop == 2 &&
01005 loop[0]->objType == DO_TABLE &&
01006 loop[1]->objType == DO_CONSTRAINT &&
01007 ((ConstraintInfo *) loop[1])->contype == 'c' &&
01008 ((ConstraintInfo *) loop[1])->contable == (TableInfo *) loop[0])
01009 {
01010 repairTableConstraintLoop(loop[0], loop[1]);
01011 return;
01012 }
01013 if (nLoop == 2 &&
01014 loop[1]->objType == DO_TABLE &&
01015 loop[0]->objType == DO_CONSTRAINT &&
01016 ((ConstraintInfo *) loop[0])->contype == 'c' &&
01017 ((ConstraintInfo *) loop[0])->contable == (TableInfo *) loop[1])
01018 {
01019 repairTableConstraintLoop(loop[1], loop[0]);
01020 return;
01021 }
01022
01023
01024 if (nLoop > 2)
01025 {
01026 for (i = 0; i < nLoop; i++)
01027 {
01028 if (loop[i]->objType == DO_TABLE)
01029 {
01030 for (j = 0; j < nLoop; j++)
01031 {
01032 if (loop[j]->objType == DO_CONSTRAINT &&
01033 ((ConstraintInfo *) loop[j])->contype == 'c' &&
01034 ((ConstraintInfo *) loop[j])->contable == (TableInfo *) loop[i])
01035 {
01036 repairTableConstraintMultiLoop(loop[i], loop[j]);
01037 return;
01038 }
01039 }
01040 }
01041 }
01042 }
01043
01044
01045 if (nLoop == 2 &&
01046 loop[0]->objType == DO_TABLE &&
01047 loop[1]->objType == DO_ATTRDEF &&
01048 ((AttrDefInfo *) loop[1])->adtable == (TableInfo *) loop[0])
01049 {
01050 repairTableAttrDefLoop(loop[0], loop[1]);
01051 return;
01052 }
01053 if (nLoop == 2 &&
01054 loop[1]->objType == DO_TABLE &&
01055 loop[0]->objType == DO_ATTRDEF &&
01056 ((AttrDefInfo *) loop[0])->adtable == (TableInfo *) loop[1])
01057 {
01058 repairTableAttrDefLoop(loop[1], loop[0]);
01059 return;
01060 }
01061
01062
01063 if (nLoop > 2)
01064 {
01065 for (i = 0; i < nLoop; i++)
01066 {
01067 if (loop[i]->objType == DO_TABLE)
01068 {
01069 for (j = 0; j < nLoop; j++)
01070 {
01071 if (loop[j]->objType == DO_ATTRDEF &&
01072 ((AttrDefInfo *) loop[j])->adtable == (TableInfo *) loop[i])
01073 {
01074 repairTableAttrDefMultiLoop(loop[i], loop[j]);
01075 return;
01076 }
01077 }
01078 }
01079 }
01080 }
01081
01082
01083 if (nLoop == 2 &&
01084 loop[0]->objType == DO_TYPE &&
01085 loop[1]->objType == DO_CONSTRAINT &&
01086 ((ConstraintInfo *) loop[1])->contype == 'c' &&
01087 ((ConstraintInfo *) loop[1])->condomain == (TypeInfo *) loop[0])
01088 {
01089 repairDomainConstraintLoop(loop[0], loop[1]);
01090 return;
01091 }
01092 if (nLoop == 2 &&
01093 loop[1]->objType == DO_TYPE &&
01094 loop[0]->objType == DO_CONSTRAINT &&
01095 ((ConstraintInfo *) loop[0])->contype == 'c' &&
01096 ((ConstraintInfo *) loop[0])->condomain == (TypeInfo *) loop[1])
01097 {
01098 repairDomainConstraintLoop(loop[1], loop[0]);
01099 return;
01100 }
01101
01102
01103 if (nLoop > 2)
01104 {
01105 for (i = 0; i < nLoop; i++)
01106 {
01107 if (loop[i]->objType == DO_TYPE)
01108 {
01109 for (j = 0; j < nLoop; j++)
01110 {
01111 if (loop[j]->objType == DO_CONSTRAINT &&
01112 ((ConstraintInfo *) loop[j])->contype == 'c' &&
01113 ((ConstraintInfo *) loop[j])->condomain == (TypeInfo *) loop[i])
01114 {
01115 repairDomainConstraintMultiLoop(loop[i], loop[j]);
01116 return;
01117 }
01118 }
01119 }
01120 }
01121 }
01122
01123
01124
01125
01126
01127
01128 for (i = 0; i < nLoop; i++)
01129 {
01130 if (loop[i]->objType != DO_TABLE_DATA)
01131 break;
01132 }
01133 if (i >= nLoop)
01134 {
01135 write_msg(NULL, "NOTICE: there are circular foreign-key constraints among these table(s):\n");
01136 for (i = 0; i < nLoop; i++)
01137 write_msg(NULL, " %s\n", loop[i]->name);
01138 write_msg(NULL, "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.\n");
01139 write_msg(NULL, "Consider using a full dump instead of a --data-only dump to avoid this problem.\n");
01140 if (nLoop > 1)
01141 removeObjectDependency(loop[0], loop[1]->dumpId);
01142 else
01143 removeObjectDependency(loop[0], loop[0]->dumpId);
01144 return;
01145 }
01146
01147
01148
01149
01150
01151 write_msg(modulename, "WARNING: could not resolve dependency loop among these items:\n");
01152 for (i = 0; i < nLoop; i++)
01153 {
01154 char buf[1024];
01155
01156 describeDumpableObject(loop[i], buf, sizeof(buf));
01157 write_msg(modulename, " %s\n", buf);
01158 }
01159
01160 if (nLoop > 1)
01161 removeObjectDependency(loop[0], loop[1]->dumpId);
01162 else
01163 removeObjectDependency(loop[0], loop[0]->dumpId);
01164 }
01165
01166
01167
01168
01169
01170
01171 static void
01172 describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
01173 {
01174 switch (obj->objType)
01175 {
01176 case DO_NAMESPACE:
01177 snprintf(buf, bufsize,
01178 "SCHEMA %s (ID %d OID %u)",
01179 obj->name, obj->dumpId, obj->catId.oid);
01180 return;
01181 case DO_EXTENSION:
01182 snprintf(buf, bufsize,
01183 "EXTENSION %s (ID %d OID %u)",
01184 obj->name, obj->dumpId, obj->catId.oid);
01185 return;
01186 case DO_TYPE:
01187 snprintf(buf, bufsize,
01188 "TYPE %s (ID %d OID %u)",
01189 obj->name, obj->dumpId, obj->catId.oid);
01190 return;
01191 case DO_SHELL_TYPE:
01192 snprintf(buf, bufsize,
01193 "SHELL TYPE %s (ID %d OID %u)",
01194 obj->name, obj->dumpId, obj->catId.oid);
01195 return;
01196 case DO_FUNC:
01197 snprintf(buf, bufsize,
01198 "FUNCTION %s (ID %d OID %u)",
01199 obj->name, obj->dumpId, obj->catId.oid);
01200 return;
01201 case DO_AGG:
01202 snprintf(buf, bufsize,
01203 "AGGREGATE %s (ID %d OID %u)",
01204 obj->name, obj->dumpId, obj->catId.oid);
01205 return;
01206 case DO_OPERATOR:
01207 snprintf(buf, bufsize,
01208 "OPERATOR %s (ID %d OID %u)",
01209 obj->name, obj->dumpId, obj->catId.oid);
01210 return;
01211 case DO_OPCLASS:
01212 snprintf(buf, bufsize,
01213 "OPERATOR CLASS %s (ID %d OID %u)",
01214 obj->name, obj->dumpId, obj->catId.oid);
01215 return;
01216 case DO_OPFAMILY:
01217 snprintf(buf, bufsize,
01218 "OPERATOR FAMILY %s (ID %d OID %u)",
01219 obj->name, obj->dumpId, obj->catId.oid);
01220 return;
01221 case DO_COLLATION:
01222 snprintf(buf, bufsize,
01223 "COLLATION %s (ID %d OID %u)",
01224 obj->name, obj->dumpId, obj->catId.oid);
01225 return;
01226 case DO_CONVERSION:
01227 snprintf(buf, bufsize,
01228 "CONVERSION %s (ID %d OID %u)",
01229 obj->name, obj->dumpId, obj->catId.oid);
01230 return;
01231 case DO_TABLE:
01232 snprintf(buf, bufsize,
01233 "TABLE %s (ID %d OID %u)",
01234 obj->name, obj->dumpId, obj->catId.oid);
01235 return;
01236 case DO_ATTRDEF:
01237 snprintf(buf, bufsize,
01238 "ATTRDEF %s.%s (ID %d OID %u)",
01239 ((AttrDefInfo *) obj)->adtable->dobj.name,
01240 ((AttrDefInfo *) obj)->adtable->attnames[((AttrDefInfo *) obj)->adnum - 1],
01241 obj->dumpId, obj->catId.oid);
01242 return;
01243 case DO_INDEX:
01244 snprintf(buf, bufsize,
01245 "INDEX %s (ID %d OID %u)",
01246 obj->name, obj->dumpId, obj->catId.oid);
01247 return;
01248 case DO_REFRESH_MATVIEW:
01249 snprintf(buf, bufsize,
01250 "REFRESH MATERIALIZED VIEW %s (ID %d OID %u)",
01251 obj->name, obj->dumpId, obj->catId.oid);
01252 return;
01253 case DO_RULE:
01254 snprintf(buf, bufsize,
01255 "RULE %s (ID %d OID %u)",
01256 obj->name, obj->dumpId, obj->catId.oid);
01257 return;
01258 case DO_TRIGGER:
01259 snprintf(buf, bufsize,
01260 "TRIGGER %s (ID %d OID %u)",
01261 obj->name, obj->dumpId, obj->catId.oid);
01262 return;
01263 case DO_EVENT_TRIGGER:
01264 snprintf(buf, bufsize,
01265 "EVENT TRIGGER %s (ID %d OID %u)",
01266 obj->name, obj->dumpId, obj->catId.oid);
01267 return;
01268 case DO_CONSTRAINT:
01269 snprintf(buf, bufsize,
01270 "CONSTRAINT %s (ID %d OID %u)",
01271 obj->name, obj->dumpId, obj->catId.oid);
01272 return;
01273 case DO_FK_CONSTRAINT:
01274 snprintf(buf, bufsize,
01275 "FK CONSTRAINT %s (ID %d OID %u)",
01276 obj->name, obj->dumpId, obj->catId.oid);
01277 return;
01278 case DO_PROCLANG:
01279 snprintf(buf, bufsize,
01280 "PROCEDURAL LANGUAGE %s (ID %d OID %u)",
01281 obj->name, obj->dumpId, obj->catId.oid);
01282 return;
01283 case DO_CAST:
01284 snprintf(buf, bufsize,
01285 "CAST %u to %u (ID %d OID %u)",
01286 ((CastInfo *) obj)->castsource,
01287 ((CastInfo *) obj)->casttarget,
01288 obj->dumpId, obj->catId.oid);
01289 return;
01290 case DO_TABLE_DATA:
01291 snprintf(buf, bufsize,
01292 "TABLE DATA %s (ID %d OID %u)",
01293 obj->name, obj->dumpId, obj->catId.oid);
01294 return;
01295 case DO_DUMMY_TYPE:
01296 snprintf(buf, bufsize,
01297 "DUMMY TYPE %s (ID %d OID %u)",
01298 obj->name, obj->dumpId, obj->catId.oid);
01299 return;
01300 case DO_TSPARSER:
01301 snprintf(buf, bufsize,
01302 "TEXT SEARCH PARSER %s (ID %d OID %u)",
01303 obj->name, obj->dumpId, obj->catId.oid);
01304 return;
01305 case DO_TSDICT:
01306 snprintf(buf, bufsize,
01307 "TEXT SEARCH DICTIONARY %s (ID %d OID %u)",
01308 obj->name, obj->dumpId, obj->catId.oid);
01309 return;
01310 case DO_TSTEMPLATE:
01311 snprintf(buf, bufsize,
01312 "TEXT SEARCH TEMPLATE %s (ID %d OID %u)",
01313 obj->name, obj->dumpId, obj->catId.oid);
01314 return;
01315 case DO_TSCONFIG:
01316 snprintf(buf, bufsize,
01317 "TEXT SEARCH CONFIGURATION %s (ID %d OID %u)",
01318 obj->name, obj->dumpId, obj->catId.oid);
01319 return;
01320 case DO_FDW:
01321 snprintf(buf, bufsize,
01322 "FOREIGN DATA WRAPPER %s (ID %d OID %u)",
01323 obj->name, obj->dumpId, obj->catId.oid);
01324 return;
01325 case DO_FOREIGN_SERVER:
01326 snprintf(buf, bufsize,
01327 "FOREIGN SERVER %s (ID %d OID %u)",
01328 obj->name, obj->dumpId, obj->catId.oid);
01329 return;
01330 case DO_DEFAULT_ACL:
01331 snprintf(buf, bufsize,
01332 "DEFAULT ACL %s (ID %d OID %u)",
01333 obj->name, obj->dumpId, obj->catId.oid);
01334 return;
01335 case DO_BLOB:
01336 snprintf(buf, bufsize,
01337 "BLOB (ID %d OID %u)",
01338 obj->dumpId, obj->catId.oid);
01339 return;
01340 case DO_BLOB_DATA:
01341 snprintf(buf, bufsize,
01342 "BLOB DATA (ID %d)",
01343 obj->dumpId);
01344 return;
01345 case DO_PRE_DATA_BOUNDARY:
01346 snprintf(buf, bufsize,
01347 "PRE-DATA BOUNDARY (ID %d)",
01348 obj->dumpId);
01349 return;
01350 case DO_POST_DATA_BOUNDARY:
01351 snprintf(buf, bufsize,
01352 "POST-DATA BOUNDARY (ID %d)",
01353 obj->dumpId);
01354 return;
01355 }
01356
01357 snprintf(buf, bufsize,
01358 "object type %d (ID %d OID %u)",
01359 (int) obj->objType,
01360 obj->dumpId, obj->catId.oid);
01361 }