PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pg_dump_sort.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_class_d.h"
#include "common/int.h"
#include "lib/binaryheap.h"
#include "pg_backup_utils.h"
#include "pg_dump.h"
Include dependency graph for pg_dump_sort.c:

Go to the source code of this file.

Enumerations

enum  dbObjectTypePriorities {
  PRIO_NAMESPACE = 1 , PRIO_PROCLANG , PRIO_COLLATION , PRIO_TRANSFORM ,
  PRIO_EXTENSION , PRIO_TYPE , PRIO_CAST , PRIO_FUNC ,
  PRIO_AGG , PRIO_ACCESS_METHOD , PRIO_OPERATOR , PRIO_OPFAMILY ,
  PRIO_CONVERSION , PRIO_TSPARSER , PRIO_TSTEMPLATE , PRIO_TSDICT ,
  PRIO_TSCONFIG , PRIO_FDW , PRIO_FOREIGN_SERVER , PRIO_TABLE ,
  PRIO_TABLE_ATTACH , PRIO_DUMMY_TYPE , PRIO_ATTRDEF , PRIO_LARGE_OBJECT ,
  PRIO_PRE_DATA_BOUNDARY , PRIO_TABLE_DATA , PRIO_SEQUENCE_SET , PRIO_LARGE_OBJECT_DATA ,
  PRIO_STATISTICS_DATA_DATA , PRIO_POST_DATA_BOUNDARY , PRIO_CONSTRAINT , PRIO_INDEX ,
  PRIO_INDEX_ATTACH , PRIO_STATSEXT , PRIO_RULE , PRIO_TRIGGER ,
  PRIO_FK_CONSTRAINT , PRIO_POLICY , PRIO_PUBLICATION , PRIO_PUBLICATION_REL ,
  PRIO_PUBLICATION_TABLE_IN_SCHEMA , PRIO_SUBSCRIPTION , PRIO_SUBSCRIPTION_REL , PRIO_DEFAULT_ACL ,
  PRIO_EVENT_TRIGGER , PRIO_REFRESH_MATVIEW
}
 

Functions

 StaticAssertDecl (lengthof(dbObjectTypePriority)==NUM_DUMPABLE_OBJECT_TYPES, "array length mismatch")
 
static int DOTypeNameCompare (const void *p1, const void *p2)
 
static bool TopoSort (DumpableObject **objs, int numObjs, DumpableObject **ordering, int *nOrdering)
 
static void findDependencyLoops (DumpableObject **objs, int nObjs, int totObjs)
 
static int findLoop (DumpableObject *obj, DumpId startPoint, bool *processed, DumpId *searchFailed, DumpableObject **workspace, int depth)
 
static void repairDependencyLoop (DumpableObject **loop, int nLoop)
 
static void describeDumpableObject (DumpableObject *obj, char *buf, int bufsize)
 
static int int_cmp (void *a, void *b, void *arg)
 
void sortDumpableObjectsByTypeName (DumpableObject **objs, int numObjs)
 
void sortDumpableObjects (DumpableObject **objs, int numObjs, DumpId preBoundaryId, DumpId postBoundaryId)
 
static void repairTypeFuncLoop (DumpableObject *typeobj, DumpableObject *funcobj)
 
static void repairViewRuleLoop (DumpableObject *viewobj, DumpableObject *ruleobj)
 
static void repairViewRuleMultiLoop (DumpableObject *viewobj, DumpableObject *ruleobj)
 
static void repairMatViewBoundaryMultiLoop (DumpableObject *boundaryobj, DumpableObject *nextobj)
 
static void repairFunctionBoundaryMultiLoop (DumpableObject *boundaryobj, DumpableObject *nextobj)
 
static void repairTableConstraintLoop (DumpableObject *tableobj, DumpableObject *constraintobj)
 
static void repairTableConstraintMultiLoop (DumpableObject *tableobj, DumpableObject *constraintobj)
 
static void repairTableAttrDefLoop (DumpableObject *tableobj, DumpableObject *attrdefobj)
 
static void repairTableAttrDefMultiLoop (DumpableObject *tableobj, DumpableObject *attrdefobj)
 
static void repairDomainConstraintLoop (DumpableObject *domainobj, DumpableObject *constraintobj)
 
static void repairDomainConstraintMultiLoop (DumpableObject *domainobj, DumpableObject *constraintobj)
 
static void repairIndexLoop (DumpableObject *partedindex, DumpableObject *partindex)
 

Variables

static const int dbObjectTypePriority []
 
static DumpId preDataBoundId
 
static DumpId postDataBoundId
 

Enumeration Type Documentation

◆ dbObjectTypePriorities

Enumerator
PRIO_NAMESPACE 
PRIO_PROCLANG 
PRIO_COLLATION 
PRIO_TRANSFORM 
PRIO_EXTENSION 
PRIO_TYPE 
PRIO_CAST 
PRIO_FUNC 
PRIO_AGG 
PRIO_ACCESS_METHOD 
PRIO_OPERATOR 
PRIO_OPFAMILY 
PRIO_CONVERSION 
PRIO_TSPARSER 
PRIO_TSTEMPLATE 
PRIO_TSDICT 
PRIO_TSCONFIG 
PRIO_FDW 
PRIO_FOREIGN_SERVER 
PRIO_TABLE 
PRIO_TABLE_ATTACH 
PRIO_DUMMY_TYPE 
PRIO_ATTRDEF 
PRIO_LARGE_OBJECT 
PRIO_PRE_DATA_BOUNDARY 
PRIO_TABLE_DATA 
PRIO_SEQUENCE_SET 
PRIO_LARGE_OBJECT_DATA 
PRIO_STATISTICS_DATA_DATA 
PRIO_POST_DATA_BOUNDARY 
PRIO_CONSTRAINT 
PRIO_INDEX 
PRIO_INDEX_ATTACH 
PRIO_STATSEXT 
PRIO_RULE 
PRIO_TRIGGER 
PRIO_FK_CONSTRAINT 
PRIO_POLICY 
PRIO_PUBLICATION 
PRIO_PUBLICATION_REL 
PRIO_PUBLICATION_TABLE_IN_SCHEMA 
PRIO_SUBSCRIPTION 
PRIO_SUBSCRIPTION_REL 
PRIO_DEFAULT_ACL 
PRIO_EVENT_TRIGGER 
PRIO_REFRESH_MATVIEW 

Definition at line 54 of file pg_dump_sort.c.

55{
61 PRIO_TYPE, /* used for DO_TYPE and DO_SHELL_TYPE */
67 PRIO_OPFAMILY, /* used for DO_OPFAMILY and DO_OPCLASS */
80 PRIO_PRE_DATA_BOUNDARY, /* boundary! */
85 PRIO_POST_DATA_BOUNDARY, /* boundary! */
99 PRIO_DEFAULT_ACL, /* done in ACL pass */
100 PRIO_EVENT_TRIGGER, /* must be next to last! */
101 PRIO_REFRESH_MATVIEW /* must be last! */
102};
@ PRIO_EVENT_TRIGGER
Definition: pg_dump_sort.c:100
@ PRIO_SUBSCRIPTION
Definition: pg_dump_sort.c:97
@ PRIO_FDW
Definition: pg_dump_sort.c:73
@ PRIO_SUBSCRIPTION_REL
Definition: pg_dump_sort.c:98
@ PRIO_INDEX_ATTACH
Definition: pg_dump_sort.c:88
@ PRIO_FK_CONSTRAINT
Definition: pg_dump_sort.c:92
@ PRIO_STATISTICS_DATA_DATA
Definition: pg_dump_sort.c:84
@ PRIO_TSCONFIG
Definition: pg_dump_sort.c:72
@ PRIO_POST_DATA_BOUNDARY
Definition: pg_dump_sort.c:85
@ PRIO_PUBLICATION
Definition: pg_dump_sort.c:94
@ PRIO_PUBLICATION_TABLE_IN_SCHEMA
Definition: pg_dump_sort.c:96
@ PRIO_TABLE
Definition: pg_dump_sort.c:75
@ PRIO_DEFAULT_ACL
Definition: pg_dump_sort.c:99
@ PRIO_CAST
Definition: pg_dump_sort.c:62
@ PRIO_AGG
Definition: pg_dump_sort.c:64
@ PRIO_PROCLANG
Definition: pg_dump_sort.c:57
@ PRIO_LARGE_OBJECT
Definition: pg_dump_sort.c:79
@ PRIO_CONVERSION
Definition: pg_dump_sort.c:68
@ PRIO_FUNC
Definition: pg_dump_sort.c:63
@ PRIO_CONSTRAINT
Definition: pg_dump_sort.c:86
@ PRIO_REFRESH_MATVIEW
Definition: pg_dump_sort.c:101
@ PRIO_POLICY
Definition: pg_dump_sort.c:93
@ PRIO_STATSEXT
Definition: pg_dump_sort.c:89
@ PRIO_EXTENSION
Definition: pg_dump_sort.c:60
@ PRIO_TSPARSER
Definition: pg_dump_sort.c:69
@ PRIO_DUMMY_TYPE
Definition: pg_dump_sort.c:77
@ PRIO_OPERATOR
Definition: pg_dump_sort.c:66
@ PRIO_RULE
Definition: pg_dump_sort.c:90
@ PRIO_NAMESPACE
Definition: pg_dump_sort.c:56
@ PRIO_PUBLICATION_REL
Definition: pg_dump_sort.c:95
@ PRIO_FOREIGN_SERVER
Definition: pg_dump_sort.c:74
@ PRIO_SEQUENCE_SET
Definition: pg_dump_sort.c:82
@ PRIO_LARGE_OBJECT_DATA
Definition: pg_dump_sort.c:83
@ PRIO_TSDICT
Definition: pg_dump_sort.c:71
@ PRIO_ACCESS_METHOD
Definition: pg_dump_sort.c:65
@ PRIO_ATTRDEF
Definition: pg_dump_sort.c:78
@ PRIO_PRE_DATA_BOUNDARY
Definition: pg_dump_sort.c:80
@ PRIO_COLLATION
Definition: pg_dump_sort.c:58
@ PRIO_INDEX
Definition: pg_dump_sort.c:87
@ PRIO_TRIGGER
Definition: pg_dump_sort.c:91
@ PRIO_TYPE
Definition: pg_dump_sort.c:61
@ PRIO_OPFAMILY
Definition: pg_dump_sort.c:67
@ PRIO_TSTEMPLATE
Definition: pg_dump_sort.c:70
@ PRIO_TRANSFORM
Definition: pg_dump_sort.c:59
@ PRIO_TABLE_DATA
Definition: pg_dump_sort.c:81
@ PRIO_TABLE_ATTACH
Definition: pg_dump_sort.c:76

Function Documentation

◆ describeDumpableObject()

static void describeDumpableObject ( DumpableObject obj,
char *  buf,
int  bufsize 
)
static

Definition at line 1286 of file pg_dump_sort.c.

1287{
1288 switch (obj->objType)
1289 {
1290 case DO_NAMESPACE:
1292 "SCHEMA %s (ID %d OID %u)",
1293 obj->name, obj->dumpId, obj->catId.oid);
1294 return;
1295 case DO_EXTENSION:
1297 "EXTENSION %s (ID %d OID %u)",
1298 obj->name, obj->dumpId, obj->catId.oid);
1299 return;
1300 case DO_TYPE:
1302 "TYPE %s (ID %d OID %u)",
1303 obj->name, obj->dumpId, obj->catId.oid);
1304 return;
1305 case DO_SHELL_TYPE:
1307 "SHELL TYPE %s (ID %d OID %u)",
1308 obj->name, obj->dumpId, obj->catId.oid);
1309 return;
1310 case DO_FUNC:
1312 "FUNCTION %s (ID %d OID %u)",
1313 obj->name, obj->dumpId, obj->catId.oid);
1314 return;
1315 case DO_AGG:
1317 "AGGREGATE %s (ID %d OID %u)",
1318 obj->name, obj->dumpId, obj->catId.oid);
1319 return;
1320 case DO_OPERATOR:
1322 "OPERATOR %s (ID %d OID %u)",
1323 obj->name, obj->dumpId, obj->catId.oid);
1324 return;
1325 case DO_ACCESS_METHOD:
1327 "ACCESS METHOD %s (ID %d OID %u)",
1328 obj->name, obj->dumpId, obj->catId.oid);
1329 return;
1330 case DO_OPCLASS:
1332 "OPERATOR CLASS %s (ID %d OID %u)",
1333 obj->name, obj->dumpId, obj->catId.oid);
1334 return;
1335 case DO_OPFAMILY:
1337 "OPERATOR FAMILY %s (ID %d OID %u)",
1338 obj->name, obj->dumpId, obj->catId.oid);
1339 return;
1340 case DO_COLLATION:
1342 "COLLATION %s (ID %d OID %u)",
1343 obj->name, obj->dumpId, obj->catId.oid);
1344 return;
1345 case DO_CONVERSION:
1347 "CONVERSION %s (ID %d OID %u)",
1348 obj->name, obj->dumpId, obj->catId.oid);
1349 return;
1350 case DO_TABLE:
1352 "TABLE %s (ID %d OID %u)",
1353 obj->name, obj->dumpId, obj->catId.oid);
1354 return;
1355 case DO_TABLE_ATTACH:
1357 "TABLE ATTACH %s (ID %d)",
1358 obj->name, obj->dumpId);
1359 return;
1360 case DO_ATTRDEF:
1362 "ATTRDEF %s.%s (ID %d OID %u)",
1363 ((AttrDefInfo *) obj)->adtable->dobj.name,
1364 ((AttrDefInfo *) obj)->adtable->attnames[((AttrDefInfo *) obj)->adnum - 1],
1365 obj->dumpId, obj->catId.oid);
1366 return;
1367 case DO_INDEX:
1369 "INDEX %s (ID %d OID %u)",
1370 obj->name, obj->dumpId, obj->catId.oid);
1371 return;
1372 case DO_INDEX_ATTACH:
1374 "INDEX ATTACH %s (ID %d)",
1375 obj->name, obj->dumpId);
1376 return;
1377 case DO_STATSEXT:
1379 "STATISTICS %s (ID %d OID %u)",
1380 obj->name, obj->dumpId, obj->catId.oid);
1381 return;
1382 case DO_REFRESH_MATVIEW:
1384 "REFRESH MATERIALIZED VIEW %s (ID %d OID %u)",
1385 obj->name, obj->dumpId, obj->catId.oid);
1386 return;
1387 case DO_RULE:
1389 "RULE %s (ID %d OID %u)",
1390 obj->name, obj->dumpId, obj->catId.oid);
1391 return;
1392 case DO_TRIGGER:
1394 "TRIGGER %s (ID %d OID %u)",
1395 obj->name, obj->dumpId, obj->catId.oid);
1396 return;
1397 case DO_EVENT_TRIGGER:
1399 "EVENT TRIGGER %s (ID %d OID %u)",
1400 obj->name, obj->dumpId, obj->catId.oid);
1401 return;
1402 case DO_CONSTRAINT:
1404 "CONSTRAINT %s (ID %d OID %u)",
1405 obj->name, obj->dumpId, obj->catId.oid);
1406 return;
1407 case DO_FK_CONSTRAINT:
1409 "FK CONSTRAINT %s (ID %d OID %u)",
1410 obj->name, obj->dumpId, obj->catId.oid);
1411 return;
1412 case DO_PROCLANG:
1414 "PROCEDURAL LANGUAGE %s (ID %d OID %u)",
1415 obj->name, obj->dumpId, obj->catId.oid);
1416 return;
1417 case DO_CAST:
1419 "CAST %u to %u (ID %d OID %u)",
1420 ((CastInfo *) obj)->castsource,
1421 ((CastInfo *) obj)->casttarget,
1422 obj->dumpId, obj->catId.oid);
1423 return;
1424 case DO_TRANSFORM:
1426 "TRANSFORM %u lang %u (ID %d OID %u)",
1427 ((TransformInfo *) obj)->trftype,
1428 ((TransformInfo *) obj)->trflang,
1429 obj->dumpId, obj->catId.oid);
1430 return;
1431 case DO_TABLE_DATA:
1433 "TABLE DATA %s (ID %d OID %u)",
1434 obj->name, obj->dumpId, obj->catId.oid);
1435 return;
1436 case DO_SEQUENCE_SET:
1438 "SEQUENCE SET %s (ID %d OID %u)",
1439 obj->name, obj->dumpId, obj->catId.oid);
1440 return;
1441 case DO_DUMMY_TYPE:
1443 "DUMMY TYPE %s (ID %d OID %u)",
1444 obj->name, obj->dumpId, obj->catId.oid);
1445 return;
1446 case DO_TSPARSER:
1448 "TEXT SEARCH PARSER %s (ID %d OID %u)",
1449 obj->name, obj->dumpId, obj->catId.oid);
1450 return;
1451 case DO_TSDICT:
1453 "TEXT SEARCH DICTIONARY %s (ID %d OID %u)",
1454 obj->name, obj->dumpId, obj->catId.oid);
1455 return;
1456 case DO_TSTEMPLATE:
1458 "TEXT SEARCH TEMPLATE %s (ID %d OID %u)",
1459 obj->name, obj->dumpId, obj->catId.oid);
1460 return;
1461 case DO_TSCONFIG:
1463 "TEXT SEARCH CONFIGURATION %s (ID %d OID %u)",
1464 obj->name, obj->dumpId, obj->catId.oid);
1465 return;
1466 case DO_FDW:
1468 "FOREIGN DATA WRAPPER %s (ID %d OID %u)",
1469 obj->name, obj->dumpId, obj->catId.oid);
1470 return;
1471 case DO_FOREIGN_SERVER:
1473 "FOREIGN SERVER %s (ID %d OID %u)",
1474 obj->name, obj->dumpId, obj->catId.oid);
1475 return;
1476 case DO_DEFAULT_ACL:
1478 "DEFAULT ACL %s (ID %d OID %u)",
1479 obj->name, obj->dumpId, obj->catId.oid);
1480 return;
1481 case DO_LARGE_OBJECT:
1483 "LARGE OBJECT (ID %d OID %u)",
1484 obj->dumpId, obj->catId.oid);
1485 return;
1488 "LARGE OBJECT DATA (ID %d)",
1489 obj->dumpId);
1490 return;
1491 case DO_POLICY:
1493 "POLICY (ID %d OID %u)",
1494 obj->dumpId, obj->catId.oid);
1495 return;
1496 case DO_PUBLICATION:
1498 "PUBLICATION (ID %d OID %u)",
1499 obj->dumpId, obj->catId.oid);
1500 return;
1501 case DO_PUBLICATION_REL:
1503 "PUBLICATION TABLE (ID %d OID %u)",
1504 obj->dumpId, obj->catId.oid);
1505 return;
1508 "PUBLICATION TABLES IN SCHEMA (ID %d OID %u)",
1509 obj->dumpId, obj->catId.oid);
1510 return;
1511 case DO_SUBSCRIPTION:
1513 "SUBSCRIPTION (ID %d OID %u)",
1514 obj->dumpId, obj->catId.oid);
1515 return;
1518 "SUBSCRIPTION TABLE (ID %d OID %u)",
1519 obj->dumpId, obj->catId.oid);
1520 return;
1523 "PRE-DATA BOUNDARY (ID %d)",
1524 obj->dumpId);
1525 return;
1528 "POST-DATA BOUNDARY (ID %d)",
1529 obj->dumpId);
1530 return;
1531 case DO_REL_STATS:
1533 "RELATION STATISTICS FOR %s (ID %d OID %u)",
1534 obj->name, obj->dumpId, obj->catId.oid);
1535 return;
1536 }
1537 /* shouldn't get here */
1539 "object type %d (ID %d OID %u)",
1540 (int) obj->objType,
1541 obj->dumpId, obj->catId.oid);
1542}
#define bufsize
Definition: indent_globs.h:36
@ DO_EVENT_TRIGGER
Definition: pg_dump.h:80
@ DO_REFRESH_MATVIEW
Definition: pg_dump.h:81
@ DO_POLICY
Definition: pg_dump.h:82
@ DO_CAST
Definition: pg_dump.h:64
@ DO_FOREIGN_SERVER
Definition: pg_dump.h:73
@ DO_PRE_DATA_BOUNDARY
Definition: pg_dump.h:78
@ DO_PROCLANG
Definition: pg_dump.h:63
@ DO_TYPE
Definition: pg_dump.h:43
@ DO_INDEX
Definition: pg_dump.h:56
@ DO_COLLATION
Definition: pg_dump.h:51
@ DO_LARGE_OBJECT
Definition: pg_dump.h:76
@ DO_TSCONFIG
Definition: pg_dump.h:71
@ DO_OPERATOR
Definition: pg_dump.h:47
@ DO_FK_CONSTRAINT
Definition: pg_dump.h:62
@ DO_CONSTRAINT
Definition: pg_dump.h:61
@ DO_SUBSCRIPTION
Definition: pg_dump.h:87
@ DO_DEFAULT_ACL
Definition: pg_dump.h:74
@ DO_FDW
Definition: pg_dump.h:72
@ DO_SUBSCRIPTION_REL
Definition: pg_dump.h:88
@ DO_REL_STATS
Definition: pg_dump.h:86
@ DO_SEQUENCE_SET
Definition: pg_dump.h:66
@ DO_ATTRDEF
Definition: pg_dump.h:55
@ DO_PUBLICATION_REL
Definition: pg_dump.h:84
@ DO_TABLE_ATTACH
Definition: pg_dump.h:54
@ DO_OPCLASS
Definition: pg_dump.h:49
@ DO_INDEX_ATTACH
Definition: pg_dump.h:57
@ DO_TSTEMPLATE
Definition: pg_dump.h:70
@ DO_STATSEXT
Definition: pg_dump.h:58
@ DO_FUNC
Definition: pg_dump.h:45
@ DO_POST_DATA_BOUNDARY
Definition: pg_dump.h:79
@ DO_LARGE_OBJECT_DATA
Definition: pg_dump.h:77
@ DO_OPFAMILY
Definition: pg_dump.h:50
@ DO_TRANSFORM
Definition: pg_dump.h:75
@ DO_ACCESS_METHOD
Definition: pg_dump.h:48
@ DO_PUBLICATION_TABLE_IN_SCHEMA
Definition: pg_dump.h:85
@ DO_CONVERSION
Definition: pg_dump.h:52
@ DO_TRIGGER
Definition: pg_dump.h:60
@ DO_RULE
Definition: pg_dump.h:59
@ DO_DUMMY_TYPE
Definition: pg_dump.h:67
@ DO_TSDICT
Definition: pg_dump.h:69
@ DO_TSPARSER
Definition: pg_dump.h:68
@ DO_EXTENSION
Definition: pg_dump.h:42
@ DO_TABLE_DATA
Definition: pg_dump.h:65
@ DO_PUBLICATION
Definition: pg_dump.h:83
@ DO_TABLE
Definition: pg_dump.h:53
@ DO_NAMESPACE
Definition: pg_dump.h:41
@ DO_AGG
Definition: pg_dump.h:46
@ DO_SHELL_TYPE
Definition: pg_dump.h:44
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239
char * name
Definition: pg_dump.h:152
DumpId dumpId
Definition: pg_dump.h:151
DumpableObjectType objType
Definition: pg_dump.h:149
CatalogId catId
Definition: pg_dump.h:150

References buf, bufsize, _dumpableObject::catId, DO_ACCESS_METHOD, DO_AGG, DO_ATTRDEF, DO_CAST, DO_COLLATION, DO_CONSTRAINT, DO_CONVERSION, DO_DEFAULT_ACL, DO_DUMMY_TYPE, DO_EVENT_TRIGGER, DO_EXTENSION, DO_FDW, DO_FK_CONSTRAINT, DO_FOREIGN_SERVER, DO_FUNC, DO_INDEX, DO_INDEX_ATTACH, DO_LARGE_OBJECT, DO_LARGE_OBJECT_DATA, DO_NAMESPACE, DO_OPCLASS, DO_OPERATOR, DO_OPFAMILY, DO_POLICY, DO_POST_DATA_BOUNDARY, DO_PRE_DATA_BOUNDARY, DO_PROCLANG, DO_PUBLICATION, DO_PUBLICATION_REL, DO_PUBLICATION_TABLE_IN_SCHEMA, DO_REFRESH_MATVIEW, DO_REL_STATS, DO_RULE, DO_SEQUENCE_SET, DO_SHELL_TYPE, DO_STATSEXT, DO_SUBSCRIPTION, DO_SUBSCRIPTION_REL, DO_TABLE, DO_TABLE_ATTACH, DO_TABLE_DATA, DO_TRANSFORM, DO_TRIGGER, DO_TSCONFIG, DO_TSDICT, DO_TSPARSER, DO_TSTEMPLATE, DO_TYPE, _dumpableObject::dumpId, _dumpableObject::name, _dumpableObject::objType, CatalogId::oid, and snprintf.

Referenced by repairDependencyLoop().

◆ DOTypeNameCompare()

static int DOTypeNameCompare ( const void *  p1,
const void *  p2 
)
static

Definition at line 198 of file pg_dump_sort.c.

199{
200 DumpableObject *obj1 = *(DumpableObject *const *) p1;
201 DumpableObject *obj2 = *(DumpableObject *const *) p2;
202 int cmpval;
203
204 /* Sort by type's priority */
205 cmpval = dbObjectTypePriority[obj1->objType] -
207
208 if (cmpval != 0)
209 return cmpval;
210
211 /*
212 * Sort by namespace. Typically, all objects of the same priority would
213 * either have or not have a namespace link, but there are exceptions.
214 * Sort NULL namespace after non-NULL in such cases.
215 */
216 if (obj1->namespace)
217 {
218 if (obj2->namespace)
219 {
220 cmpval = strcmp(obj1->namespace->dobj.name,
221 obj2->namespace->dobj.name);
222 if (cmpval != 0)
223 return cmpval;
224 }
225 else
226 return -1;
227 }
228 else if (obj2->namespace)
229 return 1;
230
231 /* Sort by name */
232 cmpval = strcmp(obj1->name, obj2->name);
233 if (cmpval != 0)
234 return cmpval;
235
236 /* To have a stable sort order, break ties for some object types */
237 if (obj1->objType == DO_FUNC || obj1->objType == DO_AGG)
238 {
239 FuncInfo *fobj1 = *(FuncInfo *const *) p1;
240 FuncInfo *fobj2 = *(FuncInfo *const *) p2;
241 int i;
242
243 /* Sort by number of arguments, then argument type names */
244 cmpval = fobj1->nargs - fobj2->nargs;
245 if (cmpval != 0)
246 return cmpval;
247 for (i = 0; i < fobj1->nargs; i++)
248 {
249 TypeInfo *argtype1 = findTypeByOid(fobj1->argtypes[i]);
250 TypeInfo *argtype2 = findTypeByOid(fobj2->argtypes[i]);
251
252 if (argtype1 && argtype2)
253 {
254 if (argtype1->dobj.namespace && argtype2->dobj.namespace)
255 {
256 cmpval = strcmp(argtype1->dobj.namespace->dobj.name,
257 argtype2->dobj.namespace->dobj.name);
258 if (cmpval != 0)
259 return cmpval;
260 }
261 cmpval = strcmp(argtype1->dobj.name, argtype2->dobj.name);
262 if (cmpval != 0)
263 return cmpval;
264 }
265 }
266 }
267 else if (obj1->objType == DO_OPERATOR)
268 {
269 OprInfo *oobj1 = *(OprInfo *const *) p1;
270 OprInfo *oobj2 = *(OprInfo *const *) p2;
271
272 /* oprkind is 'l', 'r', or 'b'; this sorts prefix, postfix, infix */
273 cmpval = (oobj2->oprkind - oobj1->oprkind);
274 if (cmpval != 0)
275 return cmpval;
276 }
277 else if (obj1->objType == DO_ATTRDEF)
278 {
279 AttrDefInfo *adobj1 = *(AttrDefInfo *const *) p1;
280 AttrDefInfo *adobj2 = *(AttrDefInfo *const *) p2;
281
282 /* Sort by attribute number */
283 cmpval = (adobj1->adnum - adobj2->adnum);
284 if (cmpval != 0)
285 return cmpval;
286 }
287 else if (obj1->objType == DO_POLICY)
288 {
289 PolicyInfo *pobj1 = *(PolicyInfo *const *) p1;
290 PolicyInfo *pobj2 = *(PolicyInfo *const *) p2;
291
292 /* Sort by table name (table namespace was considered already) */
293 cmpval = strcmp(pobj1->poltable->dobj.name,
294 pobj2->poltable->dobj.name);
295 if (cmpval != 0)
296 return cmpval;
297 }
298 else if (obj1->objType == DO_RULE)
299 {
300 RuleInfo *robj1 = *(RuleInfo *const *) p1;
301 RuleInfo *robj2 = *(RuleInfo *const *) p2;
302
303 /* Sort by table name (table namespace was considered already) */
304 cmpval = strcmp(robj1->ruletable->dobj.name,
305 robj2->ruletable->dobj.name);
306 if (cmpval != 0)
307 return cmpval;
308 }
309 else if (obj1->objType == DO_TRIGGER)
310 {
311 TriggerInfo *tobj1 = *(TriggerInfo *const *) p1;
312 TriggerInfo *tobj2 = *(TriggerInfo *const *) p2;
313
314 /* Sort by table name (table namespace was considered already) */
315 cmpval = strcmp(tobj1->tgtable->dobj.name,
316 tobj2->tgtable->dobj.name);
317 if (cmpval != 0)
318 return cmpval;
319 }
320
321 /* Usually shouldn't get here, but if we do, sort by OID */
322 return oidcmp(obj1->catId.oid, obj2->catId.oid);
323}
TypeInfo * findTypeByOid(Oid oid)
Definition: common.c:876
int i
Definition: isn.c:72
#define oidcmp(x, y)
Definition: pg_dump.h:21
static const int dbObjectTypePriority[]
Definition: pg_dump_sort.c:105
Oid * argtypes
Definition: pg_dump.h:244
int nargs
Definition: pg_dump.h:243
char oprkind
Definition: pg_dump.h:260
TableInfo * poltable
Definition: pg_dump.h:642
TableInfo * ruletable
Definition: pg_dump.h:466
DumpableObject dobj
Definition: pg_dump.h:300
TableInfo * tgtable
Definition: pg_dump.h:477
DumpableObject dobj
Definition: pg_dump.h:205

References _attrDefInfo::adnum, _funcInfo::argtypes, _dumpableObject::catId, dbObjectTypePriority, DO_AGG, DO_ATTRDEF, DO_FUNC, DO_OPERATOR, DO_POLICY, DO_RULE, DO_TRIGGER, _typeInfo::dobj, _tableInfo::dobj, findTypeByOid(), i, _dumpableObject::name, _funcInfo::nargs, _dumpableObject::objType, CatalogId::oid, oidcmp, _oprInfo::oprkind, _policyInfo::poltable, _ruleInfo::ruletable, and _triggerInfo::tgtable.

Referenced by sortDumpableObjectsByTypeName().

◆ findDependencyLoops()

static void findDependencyLoops ( DumpableObject **  objs,
int  nObjs,
int  totObjs 
)
static

Definition at line 535 of file pg_dump_sort.c.

536{
537 /*
538 * We use three data structures here:
539 *
540 * processed[] is a bool array indexed by dump ID, marking the objects
541 * already processed during this invocation of findDependencyLoops().
542 *
543 * searchFailed[] is another array indexed by dump ID. searchFailed[j] is
544 * set to dump ID k if we have proven that there is no dependency path
545 * leading from object j back to start point k. This allows us to skip
546 * useless searching when there are multiple dependency paths from k to j,
547 * which is a common situation. We could use a simple bool array for
548 * this, but then we'd need to re-zero it for each start point, resulting
549 * in O(N^2) zeroing work. Using the start point's dump ID as the "true"
550 * value lets us skip clearing the array before we consider the next start
551 * point.
552 *
553 * workspace[] is an array of DumpableObject pointers, in which we try to
554 * build lists of objects constituting loops. We make workspace[] large
555 * enough to hold all the objects in TopoSort's output, which is huge
556 * overkill in most cases but could theoretically be necessary if there is
557 * a single dependency chain linking all the objects.
558 */
559 bool *processed;
560 DumpId *searchFailed;
561 DumpableObject **workspace;
562 bool fixedloop;
563 int i;
564
565 processed = (bool *) pg_malloc0((getMaxDumpId() + 1) * sizeof(bool));
566 searchFailed = (DumpId *) pg_malloc0((getMaxDumpId() + 1) * sizeof(DumpId));
567 workspace = (DumpableObject **) pg_malloc(totObjs * sizeof(DumpableObject *));
568 fixedloop = false;
569
570 for (i = 0; i < nObjs; i++)
571 {
572 DumpableObject *obj = objs[i];
573 int looplen;
574 int j;
575
576 looplen = findLoop(obj,
577 obj->dumpId,
578 processed,
579 searchFailed,
580 workspace,
581 0);
582
583 if (looplen > 0)
584 {
585 /* Found a loop, repair it */
586 repairDependencyLoop(workspace, looplen);
587 fixedloop = true;
588 /* Mark loop members as processed */
589 for (j = 0; j < looplen; j++)
590 processed[workspace[j]->dumpId] = true;
591 }
592 else
593 {
594 /*
595 * There's no loop starting at this object, but mark it processed
596 * anyway. This is not necessary for correctness, but saves later
597 * invocations of findLoop() from uselessly chasing references to
598 * such an object.
599 */
600 processed[obj->dumpId] = true;
601 }
602 }
603
604 /* We'd better have fixed at least one loop */
605 if (!fixedloop)
606 pg_fatal("could not identify dependency loop");
607
608 free(workspace);
609 free(searchFailed);
610 free(processed);
611}
DumpId getMaxDumpId(void)
Definition: common.c:731
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define free(a)
Definition: header.h:65
int j
Definition: isn.c:73
int DumpId
Definition: pg_backup.h:278
#define pg_fatal(...)
static int findLoop(DumpableObject *obj, DumpId startPoint, bool *processed, DumpId *searchFailed, DumpableObject **workspace, int depth)
Definition: pg_dump_sort.c:631
static void repairDependencyLoop(DumpableObject **loop, int nLoop)
Definition: pg_dump_sort.c:949

References _dumpableObject::dumpId, findLoop(), free, getMaxDumpId(), i, j, pg_fatal, pg_malloc(), pg_malloc0(), and repairDependencyLoop().

Referenced by sortDumpableObjects().

◆ findLoop()

static int findLoop ( DumpableObject obj,
DumpId  startPoint,
bool *  processed,
DumpId searchFailed,
DumpableObject **  workspace,
int  depth 
)
static

Definition at line 631 of file pg_dump_sort.c.

637{
638 int i;
639
640 /*
641 * Reject if obj is already processed. This test prevents us from finding
642 * loops that overlap previously-processed loops.
643 */
644 if (processed[obj->dumpId])
645 return 0;
646
647 /*
648 * If we've already proven there is no path from this object back to the
649 * startPoint, forget it.
650 */
651 if (searchFailed[obj->dumpId] == startPoint)
652 return 0;
653
654 /*
655 * Reject if obj is already present in workspace. This test prevents us
656 * from going into infinite recursion if we are given a startPoint object
657 * that links to a cycle it's not a member of, and it guarantees that we
658 * can't overflow the allocated size of workspace[].
659 */
660 for (i = 0; i < depth; i++)
661 {
662 if (workspace[i] == obj)
663 return 0;
664 }
665
666 /*
667 * Okay, tentatively add obj to workspace
668 */
669 workspace[depth++] = obj;
670
671 /*
672 * See if we've found a loop back to the desired startPoint; if so, done
673 */
674 for (i = 0; i < obj->nDeps; i++)
675 {
676 if (obj->dependencies[i] == startPoint)
677 return depth;
678 }
679
680 /*
681 * Recurse down each outgoing branch
682 */
683 for (i = 0; i < obj->nDeps; i++)
684 {
686 int newDepth;
687
688 if (!nextobj)
689 continue; /* ignore dependencies on undumped objects */
690 newDepth = findLoop(nextobj,
691 startPoint,
692 processed,
693 searchFailed,
694 workspace,
695 depth);
696 if (newDepth > 0)
697 return newDepth;
698 }
699
700 /*
701 * Remember there is no path from here back to startPoint
702 */
703 searchFailed[obj->dumpId] = startPoint;
704
705 return 0;
706}
DumpableObject * findObjectByDumpId(DumpId dumpId)
Definition: common.c:742
DumpId * dependencies
Definition: pg_dump.h:159

References _dumpableObject::dependencies, _dumpableObject::dumpId, findLoop(), findObjectByDumpId(), i, and _dumpableObject::nDeps.

Referenced by findDependencyLoops(), and findLoop().

◆ int_cmp()

static int int_cmp ( void *  a,
void *  b,
void *  arg 
)
static

Definition at line 1546 of file pg_dump_sort.c.

1547{
1548 int ai = (int) (intptr_t) a;
1549 int bi = (int) (intptr_t) b;
1550
1551 return pg_cmp_s32(ai, bi);
1552}
static int pg_cmp_s32(int32 a, int32 b)
Definition: int.h:646
int b
Definition: isn.c:69
int a
Definition: isn.c:68

References a, b, and pg_cmp_s32().

Referenced by TopoSort().

◆ repairDependencyLoop()

static void repairDependencyLoop ( DumpableObject **  loop,
int  nLoop 
)
static

Definition at line 949 of file pg_dump_sort.c.

951{
952 int i,
953 j;
954
955 /* Datatype and one of its I/O or canonicalize functions */
956 if (nLoop == 2 &&
957 loop[0]->objType == DO_TYPE &&
958 loop[1]->objType == DO_FUNC)
959 {
960 repairTypeFuncLoop(loop[0], loop[1]);
961 return;
962 }
963 if (nLoop == 2 &&
964 loop[1]->objType == DO_TYPE &&
965 loop[0]->objType == DO_FUNC)
966 {
967 repairTypeFuncLoop(loop[1], loop[0]);
968 return;
969 }
970
971 /* View (including matview) and its ON SELECT rule */
972 if (nLoop == 2 &&
973 loop[0]->objType == DO_TABLE &&
974 loop[1]->objType == DO_RULE &&
975 (((TableInfo *) loop[0])->relkind == RELKIND_VIEW ||
976 ((TableInfo *) loop[0])->relkind == RELKIND_MATVIEW) &&
977 ((RuleInfo *) loop[1])->ev_type == '1' &&
978 ((RuleInfo *) loop[1])->is_instead &&
979 ((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0])
980 {
981 repairViewRuleLoop(loop[0], loop[1]);
982 return;
983 }
984 if (nLoop == 2 &&
985 loop[1]->objType == DO_TABLE &&
986 loop[0]->objType == DO_RULE &&
987 (((TableInfo *) loop[1])->relkind == RELKIND_VIEW ||
988 ((TableInfo *) loop[1])->relkind == RELKIND_MATVIEW) &&
989 ((RuleInfo *) loop[0])->ev_type == '1' &&
990 ((RuleInfo *) loop[0])->is_instead &&
991 ((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1])
992 {
993 repairViewRuleLoop(loop[1], loop[0]);
994 return;
995 }
996
997 /* Indirect loop involving view (but not matview) and ON SELECT rule */
998 if (nLoop > 2)
999 {
1000 for (i = 0; i < nLoop; i++)
1001 {
1002 if (loop[i]->objType == DO_TABLE &&
1003 ((TableInfo *) loop[i])->relkind == RELKIND_VIEW)
1004 {
1005 for (j = 0; j < nLoop; j++)
1006 {
1007 if (loop[j]->objType == DO_RULE &&
1008 ((RuleInfo *) loop[j])->ev_type == '1' &&
1009 ((RuleInfo *) loop[j])->is_instead &&
1010 ((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i])
1011 {
1012 repairViewRuleMultiLoop(loop[i], loop[j]);
1013 return;
1014 }
1015 }
1016 }
1017 }
1018 }
1019
1020 /* Indirect loop involving matview and data boundary */
1021 if (nLoop > 2)
1022 {
1023 for (i = 0; i < nLoop; i++)
1024 {
1025 if (loop[i]->objType == DO_TABLE &&
1026 ((TableInfo *) loop[i])->relkind == RELKIND_MATVIEW)
1027 {
1028 for (j = 0; j < nLoop; j++)
1029 {
1030 if (loop[j]->objType == DO_PRE_DATA_BOUNDARY)
1031 {
1032 DumpableObject *nextobj;
1033
1034 nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
1035 repairMatViewBoundaryMultiLoop(loop[j], nextobj);
1036 return;
1037 }
1038 }
1039 }
1040 else if (loop[i]->objType == DO_REL_STATS &&
1041 ((RelStatsInfo *) loop[i])->relkind == RELKIND_MATVIEW)
1042 {
1043 for (j = 0; j < nLoop; j++)
1044 {
1045 if (loop[j]->objType == DO_POST_DATA_BOUNDARY)
1046 {
1047 DumpableObject *nextobj;
1048
1049 nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
1050 repairMatViewBoundaryMultiLoop(loop[j], nextobj);
1051 return;
1052 }
1053 }
1054 }
1055 }
1056 }
1057
1058 /* Indirect loop involving function and data boundary */
1059 if (nLoop > 2)
1060 {
1061 for (i = 0; i < nLoop; i++)
1062 {
1063 if (loop[i]->objType == DO_FUNC)
1064 {
1065 for (j = 0; j < nLoop; j++)
1066 {
1067 if (loop[j]->objType == DO_PRE_DATA_BOUNDARY)
1068 {
1069 DumpableObject *nextobj;
1070
1071 nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
1072 repairFunctionBoundaryMultiLoop(loop[j], nextobj);
1073 return;
1074 }
1075 }
1076 }
1077 }
1078 }
1079
1080 /* Table and CHECK constraint */
1081 if (nLoop == 2 &&
1082 loop[0]->objType == DO_TABLE &&
1083 loop[1]->objType == DO_CONSTRAINT &&
1084 ((ConstraintInfo *) loop[1])->contype == 'c' &&
1085 ((ConstraintInfo *) loop[1])->contable == (TableInfo *) loop[0])
1086 {
1087 repairTableConstraintLoop(loop[0], loop[1]);
1088 return;
1089 }
1090 if (nLoop == 2 &&
1091 loop[1]->objType == DO_TABLE &&
1092 loop[0]->objType == DO_CONSTRAINT &&
1093 ((ConstraintInfo *) loop[0])->contype == 'c' &&
1094 ((ConstraintInfo *) loop[0])->contable == (TableInfo *) loop[1])
1095 {
1096 repairTableConstraintLoop(loop[1], loop[0]);
1097 return;
1098 }
1099
1100 /* Indirect loop involving table and CHECK constraint */
1101 if (nLoop > 2)
1102 {
1103 for (i = 0; i < nLoop; i++)
1104 {
1105 if (loop[i]->objType == DO_TABLE)
1106 {
1107 for (j = 0; j < nLoop; j++)
1108 {
1109 if (loop[j]->objType == DO_CONSTRAINT &&
1110 ((ConstraintInfo *) loop[j])->contype == 'c' &&
1111 ((ConstraintInfo *) loop[j])->contable == (TableInfo *) loop[i])
1112 {
1113 repairTableConstraintMultiLoop(loop[i], loop[j]);
1114 return;
1115 }
1116 }
1117 }
1118 }
1119 }
1120
1121 /* Table and attribute default */
1122 if (nLoop == 2 &&
1123 loop[0]->objType == DO_TABLE &&
1124 loop[1]->objType == DO_ATTRDEF &&
1125 ((AttrDefInfo *) loop[1])->adtable == (TableInfo *) loop[0])
1126 {
1127 repairTableAttrDefLoop(loop[0], loop[1]);
1128 return;
1129 }
1130 if (nLoop == 2 &&
1131 loop[1]->objType == DO_TABLE &&
1132 loop[0]->objType == DO_ATTRDEF &&
1133 ((AttrDefInfo *) loop[0])->adtable == (TableInfo *) loop[1])
1134 {
1135 repairTableAttrDefLoop(loop[1], loop[0]);
1136 return;
1137 }
1138
1139 /* index on partitioned table and corresponding index on partition */
1140 if (nLoop == 2 &&
1141 loop[0]->objType == DO_INDEX &&
1142 loop[1]->objType == DO_INDEX)
1143 {
1144 if (((IndxInfo *) loop[0])->parentidx == loop[1]->catId.oid)
1145 {
1146 repairIndexLoop(loop[0], loop[1]);
1147 return;
1148 }
1149 else if (((IndxInfo *) loop[1])->parentidx == loop[0]->catId.oid)
1150 {
1151 repairIndexLoop(loop[1], loop[0]);
1152 return;
1153 }
1154 }
1155
1156 /* Indirect loop involving table and attribute default */
1157 if (nLoop > 2)
1158 {
1159 for (i = 0; i < nLoop; i++)
1160 {
1161 if (loop[i]->objType == DO_TABLE)
1162 {
1163 for (j = 0; j < nLoop; j++)
1164 {
1165 if (loop[j]->objType == DO_ATTRDEF &&
1166 ((AttrDefInfo *) loop[j])->adtable == (TableInfo *) loop[i])
1167 {
1168 repairTableAttrDefMultiLoop(loop[i], loop[j]);
1169 return;
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 /* Domain and CHECK constraint */
1177 if (nLoop == 2 &&
1178 loop[0]->objType == DO_TYPE &&
1179 loop[1]->objType == DO_CONSTRAINT &&
1180 ((ConstraintInfo *) loop[1])->contype == 'c' &&
1181 ((ConstraintInfo *) loop[1])->condomain == (TypeInfo *) loop[0])
1182 {
1183 repairDomainConstraintLoop(loop[0], loop[1]);
1184 return;
1185 }
1186 if (nLoop == 2 &&
1187 loop[1]->objType == DO_TYPE &&
1188 loop[0]->objType == DO_CONSTRAINT &&
1189 ((ConstraintInfo *) loop[0])->contype == 'c' &&
1190 ((ConstraintInfo *) loop[0])->condomain == (TypeInfo *) loop[1])
1191 {
1192 repairDomainConstraintLoop(loop[1], loop[0]);
1193 return;
1194 }
1195
1196 /* Indirect loop involving domain and CHECK constraint */
1197 if (nLoop > 2)
1198 {
1199 for (i = 0; i < nLoop; i++)
1200 {
1201 if (loop[i]->objType == DO_TYPE)
1202 {
1203 for (j = 0; j < nLoop; j++)
1204 {
1205 if (loop[j]->objType == DO_CONSTRAINT &&
1206 ((ConstraintInfo *) loop[j])->contype == 'c' &&
1207 ((ConstraintInfo *) loop[j])->condomain == (TypeInfo *) loop[i])
1208 {
1209 repairDomainConstraintMultiLoop(loop[i], loop[j]);
1210 return;
1211 }
1212 }
1213 }
1214 }
1215 }
1216
1217 /*
1218 * Loop of table with itself --- just ignore it.
1219 *
1220 * (Actually, what this arises from is a dependency of a table column on
1221 * another column, which happened with generated columns before v15; or a
1222 * dependency of a table column on the whole table, which happens with
1223 * partitioning. But we didn't pay attention to sub-object IDs while
1224 * collecting the dependency data, so we can't see that here.)
1225 */
1226 if (nLoop == 1)
1227 {
1228 if (loop[0]->objType == DO_TABLE)
1229 {
1230 removeObjectDependency(loop[0], loop[0]->dumpId);
1231 return;
1232 }
1233 }
1234
1235 /*
1236 * If all the objects are TABLE_DATA items, what we must have is a
1237 * circular set of foreign key constraints (or a single self-referential
1238 * table). Print an appropriate complaint and break the loop arbitrarily.
1239 */
1240 for (i = 0; i < nLoop; i++)
1241 {
1242 if (loop[i]->objType != DO_TABLE_DATA)
1243 break;
1244 }
1245 if (i >= nLoop)
1246 {
1247 pg_log_warning(ngettext("there are circular foreign-key constraints on this table:",
1248 "there are circular foreign-key constraints among these tables:",
1249 nLoop));
1250 for (i = 0; i < nLoop; i++)
1251 pg_log_warning_detail("%s", loop[i]->name);
1252 pg_log_warning_hint("You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.");
1253 pg_log_warning_hint("Consider using a full dump instead of a --data-only dump to avoid this problem.");
1254 if (nLoop > 1)
1255 removeObjectDependency(loop[0], loop[1]->dumpId);
1256 else /* must be a self-dependency */
1257 removeObjectDependency(loop[0], loop[0]->dumpId);
1258 return;
1259 }
1260
1261 /*
1262 * If we can't find a principled way to break the loop, complain and break
1263 * it in an arbitrary fashion.
1264 */
1265 pg_log_warning("could not resolve dependency loop among these items:");
1266 for (i = 0; i < nLoop; i++)
1267 {
1268 char buf[1024];
1269
1270 describeDumpableObject(loop[i], buf, sizeof(buf));
1272 }
1273
1274 if (nLoop > 1)
1275 removeObjectDependency(loop[0], loop[1]->dumpId);
1276 else /* must be a self-dependency */
1277 removeObjectDependency(loop[0], loop[0]->dumpId);
1278}
void removeObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:820
#define ngettext(s, p, n)
Definition: c.h:1152
#define pg_log_warning_hint(...)
Definition: logging.h:121
#define pg_log_warning_detail(...)
Definition: logging.h:118
static void repairMatViewBoundaryMultiLoop(DumpableObject *boundaryobj, DumpableObject *nextobj)
Definition: pg_dump_sort.c:801
static void repairTableAttrDefLoop(DumpableObject *tableobj, DumpableObject *attrdefobj)
Definition: pg_dump_sort.c:890
static void repairTableConstraintLoop(DumpableObject *tableobj, DumpableObject *constraintobj)
Definition: pg_dump_sort.c:856
static void repairTableAttrDefMultiLoop(DumpableObject *tableobj, DumpableObject *attrdefobj)
Definition: pg_dump_sort.c:898
static void repairViewRuleMultiLoop(DumpableObject *viewobj, DumpableObject *ruleobj)
Definition: pg_dump_sort.c:767
static void repairDomainConstraintLoop(DumpableObject *domainobj, DumpableObject *constraintobj)
Definition: pg_dump_sort.c:913
static void repairTableConstraintMultiLoop(DumpableObject *tableobj, DumpableObject *constraintobj)
Definition: pg_dump_sort.c:873
static void describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
static void repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
Definition: pg_dump_sort.c:716
static void repairDomainConstraintMultiLoop(DumpableObject *domainobj, DumpableObject *constraintobj)
Definition: pg_dump_sort.c:921
static void repairIndexLoop(DumpableObject *partedindex, DumpableObject *partindex)
Definition: pg_dump_sort.c:935
static void repairViewRuleLoop(DumpableObject *viewobj, DumpableObject *ruleobj)
Definition: pg_dump_sort.c:747
static void repairFunctionBoundaryMultiLoop(DumpableObject *boundaryobj, DumpableObject *nextobj)
Definition: pg_dump_sort.c:835
#define pg_log_warning(...)
Definition: pgfnames.c:24
const char * name

References buf, describeDumpableObject(), DO_ATTRDEF, DO_CONSTRAINT, DO_FUNC, DO_INDEX, DO_POST_DATA_BOUNDARY, DO_PRE_DATA_BOUNDARY, DO_REL_STATS, DO_RULE, DO_TABLE, DO_TABLE_DATA, DO_TYPE, i, j, name, ngettext, pg_log_warning, pg_log_warning_detail, pg_log_warning_hint, removeObjectDependency(), repairDomainConstraintLoop(), repairDomainConstraintMultiLoop(), repairFunctionBoundaryMultiLoop(), repairIndexLoop(), repairMatViewBoundaryMultiLoop(), repairTableAttrDefLoop(), repairTableAttrDefMultiLoop(), repairTableConstraintLoop(), repairTableConstraintMultiLoop(), repairTypeFuncLoop(), repairViewRuleLoop(), and repairViewRuleMultiLoop().

Referenced by findDependencyLoops().

◆ repairDomainConstraintLoop()

static void repairDomainConstraintLoop ( DumpableObject domainobj,
DumpableObject constraintobj 
)
static

Definition at line 913 of file pg_dump_sort.c.

915{
916 /* remove constraint's dependency on domain */
917 removeObjectDependency(constraintobj, domainobj->dumpId);
918}

References _dumpableObject::dumpId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairDomainConstraintMultiLoop()

static void repairDomainConstraintMultiLoop ( DumpableObject domainobj,
DumpableObject constraintobj 
)
static

Definition at line 921 of file pg_dump_sort.c.

923{
924 /* remove domain's dependency on constraint */
925 removeObjectDependency(domainobj, constraintobj->dumpId);
926 /* mark constraint as needing its own dump */
927 ((ConstraintInfo *) constraintobj)->separate = true;
928 /* put back constraint's dependency on domain */
929 addObjectDependency(constraintobj, domainobj->dumpId);
930 /* now that constraint is separate, it must be post-data */
931 addObjectDependency(constraintobj, postDataBoundId);
932}
void addObjectDependency(DumpableObject *dobj, DumpId refId)
Definition: common.c:795
static DumpId postDataBoundId
Definition: pg_dump_sort.c:161

References addObjectDependency(), _dumpableObject::dumpId, postDataBoundId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairFunctionBoundaryMultiLoop()

static void repairFunctionBoundaryMultiLoop ( DumpableObject boundaryobj,
DumpableObject nextobj 
)
static

Definition at line 835 of file pg_dump_sort.c.

837{
838 /* remove boundary's dependency on object after it in loop */
839 removeObjectDependency(boundaryobj, nextobj->dumpId);
840 /* if that object is a function, mark it as postponed into post-data */
841 if (nextobj->objType == DO_FUNC)
842 {
843 FuncInfo *nextinfo = (FuncInfo *) nextobj;
844
845 nextinfo->postponed_def = true;
846 }
847}
bool postponed_def
Definition: pg_dump.h:246

References DO_FUNC, _dumpableObject::dumpId, _dumpableObject::objType, _funcInfo::postponed_def, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairIndexLoop()

static void repairIndexLoop ( DumpableObject partedindex,
DumpableObject partindex 
)
static

Definition at line 935 of file pg_dump_sort.c.

937{
938 removeObjectDependency(partedindex, partindex->dumpId);
939}

References _dumpableObject::dumpId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairMatViewBoundaryMultiLoop()

static void repairMatViewBoundaryMultiLoop ( DumpableObject boundaryobj,
DumpableObject nextobj 
)
static

Definition at line 801 of file pg_dump_sort.c.

803{
804 /* remove boundary's dependency on object after it in loop */
805 removeObjectDependency(boundaryobj, nextobj->dumpId);
806
807 /*
808 * If that object is a matview or matview stats, mark it as postponed into
809 * post-data.
810 */
811 if (nextobj->objType == DO_TABLE)
812 {
813 TableInfo *nextinfo = (TableInfo *) nextobj;
814
815 if (nextinfo->relkind == RELKIND_MATVIEW)
816 nextinfo->postponed_def = true;
817 }
818 else if (nextobj->objType == DO_REL_STATS)
819 {
820 RelStatsInfo *nextinfo = (RelStatsInfo *) nextobj;
821
822 if (nextinfo->relkind == RELKIND_MATVIEW)
823 nextinfo->postponed_def = true;
824 }
825}
char relkind
Definition: pg_dump.h:444
bool postponed_def
Definition: pg_dump.h:452
char relkind
Definition: pg_dump.h:303
bool postponed_def
Definition: pg_dump.h:336

References DO_REL_STATS, DO_TABLE, _dumpableObject::dumpId, _dumpableObject::objType, _tableInfo::postponed_def, _relStatsInfo::postponed_def, _tableInfo::relkind, _relStatsInfo::relkind, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairTableAttrDefLoop()

static void repairTableAttrDefLoop ( DumpableObject tableobj,
DumpableObject attrdefobj 
)
static

Definition at line 890 of file pg_dump_sort.c.

892{
893 /* remove attrdef's dependency on table */
894 removeObjectDependency(attrdefobj, tableobj->dumpId);
895}

References _dumpableObject::dumpId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairTableAttrDefMultiLoop()

static void repairTableAttrDefMultiLoop ( DumpableObject tableobj,
DumpableObject attrdefobj 
)
static

Definition at line 898 of file pg_dump_sort.c.

900{
901 /* remove table's dependency on attrdef */
902 removeObjectDependency(tableobj, attrdefobj->dumpId);
903 /* mark attrdef as needing its own dump */
904 ((AttrDefInfo *) attrdefobj)->separate = true;
905 /* put back attrdef's dependency on table */
906 addObjectDependency(attrdefobj, tableobj->dumpId);
907}

References addObjectDependency(), _dumpableObject::dumpId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairTableConstraintLoop()

static void repairTableConstraintLoop ( DumpableObject tableobj,
DumpableObject constraintobj 
)
static

Definition at line 856 of file pg_dump_sort.c.

858{
859 /* remove constraint's dependency on table */
860 removeObjectDependency(constraintobj, tableobj->dumpId);
861}

References _dumpableObject::dumpId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairTableConstraintMultiLoop()

static void repairTableConstraintMultiLoop ( DumpableObject tableobj,
DumpableObject constraintobj 
)
static

Definition at line 873 of file pg_dump_sort.c.

875{
876 /* remove table's dependency on constraint */
877 removeObjectDependency(tableobj, constraintobj->dumpId);
878 /* mark constraint as needing its own dump */
879 ((ConstraintInfo *) constraintobj)->separate = true;
880 /* put back constraint's dependency on table */
881 addObjectDependency(constraintobj, tableobj->dumpId);
882 /* now that constraint is separate, it must be post-data */
883 addObjectDependency(constraintobj, postDataBoundId);
884}

References addObjectDependency(), _dumpableObject::dumpId, postDataBoundId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairTypeFuncLoop()

static void repairTypeFuncLoop ( DumpableObject typeobj,
DumpableObject funcobj 
)
static

Definition at line 716 of file pg_dump_sort.c.

717{
718 TypeInfo *typeInfo = (TypeInfo *) typeobj;
719
720 /* remove function's dependency on type */
721 removeObjectDependency(funcobj, typeobj->dumpId);
722
723 /* add function's dependency on shell type, instead */
724 if (typeInfo->shellType)
725 {
726 addObjectDependency(funcobj, typeInfo->shellType->dobj.dumpId);
727
728 /*
729 * Mark shell type (always including the definition, as we need the
730 * shell type defined to identify the function fully) as to be dumped
731 * if any such function is
732 */
733 if (funcobj->dump)
734 typeInfo->shellType->dobj.dump = funcobj->dump |
736 }
737}
#define DUMP_COMPONENT_DEFINITION
Definition: pg_dump.h:109
DumpComponents dump
Definition: pg_dump.h:153
DumpableObject dobj
Definition: pg_dump.h:232
struct _shellTypeInfo * shellType
Definition: pg_dump.h:224

References addObjectDependency(), _shellTypeInfo::dobj, _dumpableObject::dump, DUMP_COMPONENT_DEFINITION, _dumpableObject::dumpId, removeObjectDependency(), and _typeInfo::shellType.

Referenced by repairDependencyLoop().

◆ repairViewRuleLoop()

static void repairViewRuleLoop ( DumpableObject viewobj,
DumpableObject ruleobj 
)
static

Definition at line 747 of file pg_dump_sort.c.

749{
750 /* remove rule's dependency on view */
751 removeObjectDependency(ruleobj, viewobj->dumpId);
752 /* flags on the two objects are already set correctly for this case */
753}

References _dumpableObject::dumpId, and removeObjectDependency().

Referenced by repairDependencyLoop().

◆ repairViewRuleMultiLoop()

static void repairViewRuleMultiLoop ( DumpableObject viewobj,
DumpableObject ruleobj 
)
static

Definition at line 767 of file pg_dump_sort.c.

769{
770 TableInfo *viewinfo = (TableInfo *) viewobj;
771 RuleInfo *ruleinfo = (RuleInfo *) ruleobj;
772
773 /* remove view's dependency on rule */
774 removeObjectDependency(viewobj, ruleobj->dumpId);
775 /* mark view to be printed with a dummy definition */
776 viewinfo->dummy_view = true;
777 /* mark rule as needing its own dump */
778 ruleinfo->separate = true;
779 /* put back rule's dependency on view */
780 addObjectDependency(ruleobj, viewobj->dumpId);
781 /* now that rule is separate, it must be post-data */
783}
bool separate
Definition: pg_dump.h:470
bool dummy_view
Definition: pg_dump.h:335

References addObjectDependency(), _tableInfo::dummy_view, _dumpableObject::dumpId, postDataBoundId, removeObjectDependency(), and _ruleInfo::separate.

Referenced by repairDependencyLoop().

◆ sortDumpableObjects()

void sortDumpableObjects ( DumpableObject **  objs,
int  numObjs,
DumpId  preBoundaryId,
DumpId  postBoundaryId 
)

Definition at line 334 of file pg_dump_sort.c.

336{
337 DumpableObject **ordering;
338 int nOrdering;
339
340 if (numObjs <= 0) /* can't happen anymore ... */
341 return;
342
343 /*
344 * Saving the boundary IDs in static variables is a bit grotty, but seems
345 * better than adding them to parameter lists of subsidiary functions.
346 */
347 preDataBoundId = preBoundaryId;
348 postDataBoundId = postBoundaryId;
349
350 ordering = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *));
351 while (!TopoSort(objs, numObjs, ordering, &nOrdering))
352 findDependencyLoops(ordering, nOrdering, numObjs);
353
354 memcpy(objs, ordering, numObjs * sizeof(DumpableObject *));
355
356 free(ordering);
357}
static void findDependencyLoops(DumpableObject **objs, int nObjs, int totObjs)
Definition: pg_dump_sort.c:535
static DumpId preDataBoundId
Definition: pg_dump_sort.c:160
static bool TopoSort(DumpableObject **objs, int numObjs, DumpableObject **ordering, int *nOrdering)
Definition: pg_dump_sort.c:386

References findDependencyLoops(), free, pg_malloc(), postDataBoundId, preDataBoundId, and TopoSort().

Referenced by main().

◆ sortDumpableObjectsByTypeName()

void sortDumpableObjectsByTypeName ( DumpableObject **  objs,
int  numObjs 
)

Definition at line 190 of file pg_dump_sort.c.

191{
192 if (numObjs > 1)
193 qsort(objs, numObjs, sizeof(DumpableObject *),
195}
static int DOTypeNameCompare(const void *p1, const void *p2)
Definition: pg_dump_sort.c:198
#define qsort(a, b, c, d)
Definition: port.h:475

References DOTypeNameCompare(), and qsort.

Referenced by main().

◆ StaticAssertDecl()

StaticAssertDecl ( lengthof(dbObjectTypePriority = =NUM_DUMPABLE_OBJECT_TYPES,
"array length mismatch"   
)

◆ TopoSort()

static bool TopoSort ( DumpableObject **  objs,
int  numObjs,
DumpableObject **  ordering,
int *  nOrdering 
)
static

Definition at line 386 of file pg_dump_sort.c.

390{
391 DumpId maxDumpId = getMaxDumpId();
392 binaryheap *pendingHeap;
394 int *idMap;
395 DumpableObject *obj;
396 int i,
397 j,
398 k;
399
400 /*
401 * This is basically the same algorithm shown for topological sorting in
402 * Knuth's Volume 1. However, we would like to minimize unnecessary
403 * rearrangement of the input ordering; that is, when we have a choice of
404 * which item to output next, we always want to take the one highest in
405 * the original list. Therefore, instead of maintaining an unordered
406 * linked list of items-ready-to-output as Knuth does, we maintain a heap
407 * of their item numbers, which we can use as a priority queue. This
408 * turns the algorithm from O(N) to O(N log N) because each insertion or
409 * removal of a heap item takes O(log N) time. However, that's still
410 * plenty fast enough for this application.
411 */
412
413 *nOrdering = numObjs; /* for success return */
414
415 /* Eliminate the null case */
416 if (numObjs <= 0)
417 return true;
418
419 /* Create workspace for the above-described heap */
420 pendingHeap = binaryheap_allocate(numObjs, int_cmp, NULL);
421
422 /*
423 * Scan the constraints, and for each item in the input, generate a count
424 * of the number of constraints that say it must be before something else.
425 * The count for the item with dumpId j is stored in beforeConstraints[j].
426 * We also make a map showing the input-order index of the item with
427 * dumpId j.
428 */
429 beforeConstraints = (int *) pg_malloc0((maxDumpId + 1) * sizeof(int));
430 idMap = (int *) pg_malloc((maxDumpId + 1) * sizeof(int));
431 for (i = 0; i < numObjs; i++)
432 {
433 obj = objs[i];
434 j = obj->dumpId;
435 if (j <= 0 || j > maxDumpId)
436 pg_fatal("invalid dumpId %d", j);
437 idMap[j] = i;
438 for (j = 0; j < obj->nDeps; j++)
439 {
440 k = obj->dependencies[j];
441 if (k <= 0 || k > maxDumpId)
442 pg_fatal("invalid dependency %d", k);
444 }
445 }
446
447 /*
448 * Now initialize the heap of items-ready-to-output by filling it with the
449 * indexes of items that already have beforeConstraints[id] == 0.
450 *
451 * We enter the indexes into pendingHeap in decreasing order so that the
452 * heap invariant is satisfied at the completion of this loop. This
453 * reduces the amount of work that binaryheap_build() must do.
454 */
455 for (i = numObjs; --i >= 0;)
456 {
457 if (beforeConstraints[objs[i]->dumpId] == 0)
458 binaryheap_add_unordered(pendingHeap, (void *) (intptr_t) i);
459 }
460 binaryheap_build(pendingHeap);
461
462 /*--------------------
463 * Now emit objects, working backwards in the output list. At each step,
464 * we use the priority heap to select the last item that has no remaining
465 * before-constraints. We remove that item from the heap, output it to
466 * ordering[], and decrease the beforeConstraints count of each of the
467 * items it was constrained against. Whenever an item's beforeConstraints
468 * count is thereby decreased to zero, we insert it into the priority heap
469 * to show that it is a candidate to output. We are done when the heap
470 * becomes empty; if we have output every element then we succeeded,
471 * otherwise we failed.
472 * i = number of ordering[] entries left to output
473 * j = objs[] index of item we are outputting
474 * k = temp for scanning constraint list for item j
475 *--------------------
476 */
477 i = numObjs;
478 while (!binaryheap_empty(pendingHeap))
479 {
480 /* Select object to output by removing largest heap member */
481 j = (int) (intptr_t) binaryheap_remove_first(pendingHeap);
482 obj = objs[j];
483 /* Output candidate to ordering[] */
484 ordering[--i] = obj;
485 /* Update beforeConstraints counts of its predecessors */
486 for (k = 0; k < obj->nDeps; k++)
487 {
488 int id = obj->dependencies[k];
489
490 if ((--beforeConstraints[id]) == 0)
491 binaryheap_add(pendingHeap, (void *) (intptr_t) idMap[id]);
492 }
493 }
494
495 /*
496 * If we failed, report the objects that couldn't be output; these are the
497 * ones with beforeConstraints[] still nonzero.
498 */
499 if (i != 0)
500 {
501 k = 0;
502 for (j = 1; j <= maxDumpId; j++)
503 {
504 if (beforeConstraints[j] != 0)
505 ordering[k++] = objs[idMap[j]];
506 }
507 *nOrdering = k;
508 }
509
510 /* Done */
511 binaryheap_free(pendingHeap);
513 free(idMap);
514
515 return (i == 0);
516}
void binaryheap_build(binaryheap *heap)
Definition: binaryheap.c:138
void binaryheap_add(binaryheap *heap, bh_node_type d)
Definition: binaryheap.c:154
bh_node_type binaryheap_remove_first(binaryheap *heap)
Definition: binaryheap.c:192
void binaryheap_free(binaryheap *heap)
Definition: binaryheap.c:75
void binaryheap_add_unordered(binaryheap *heap, bh_node_type d)
Definition: binaryheap.c:116
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition: binaryheap.c:39
#define binaryheap_empty(h)
Definition: binaryheap.h:65
static int * beforeConstraints
Definition: deadlock.c:108
static int int_cmp(void *a, void *b, void *arg)

References beforeConstraints, binaryheap_add(), binaryheap_add_unordered(), binaryheap_allocate(), binaryheap_build(), binaryheap_empty, binaryheap_free(), binaryheap_remove_first(), _dumpableObject::dependencies, _dumpableObject::dumpId, free, getMaxDumpId(), i, int_cmp(), j, _dumpableObject::nDeps, pg_fatal, pg_malloc(), and pg_malloc0().

Referenced by sortDumpableObjects().

Variable Documentation

◆ dbObjectTypePriority

const int dbObjectTypePriority[]
static

Definition at line 105 of file pg_dump_sort.c.

Referenced by DOTypeNameCompare().

◆ postDataBoundId

◆ preDataBoundId

DumpId preDataBoundId
static

Definition at line 160 of file pg_dump_sort.c.

Referenced by sortDumpableObjects().