Re: FK Constraint sort order with pg_dump - Mailing list pgsql-general

From Tom Lane
Subject Re: FK Constraint sort order with pg_dump
Date
Msg-id 286980.1658436393@sss.pgh.pa.us
Whole thread Raw
In response to Re: FK Constraint sort order with pg_dump  (Christian Barthel <bch@online.de>)
List pgsql-general
Christian Barthel <bch@online.de> writes:
> On Thursday, July 21, 2022, Adrian Klaver wrote:
>> Why does it matter?

> As the comment in pg_dump.c states, logically identical schemas should
> produce identical dumps:

Agreed, but this is far from the only deficiency in DOTypeNameCompare.
If we're going to try to fill in the gaps, we should be systematic
about it.  I took a quick stab at implementing the cases it omits,
as attached.  There are still a few gaps:

* DO_OPCLASS and DO_OPFAMILY ought to have a subsidiary sort on the
access method name, since their names are only unique per-access-method.
The trouble here is that OpclassInfo/OpfamilyInfo don't provide any
way to get to the access method.  That could be fixed with more fields,
and maybe it's worth doing, but I didn't do that here.

* For casts, the cast name is consed up as the concatenation of the source
and target type names, which isn't enough to guarantee uniqueness.  We
could add the types' schema names, perhaps ... is it worth the trouble?
(Not to mention possible breakage of scripts that expect the current
naming convention.)

* Likewise for transforms, we'd need to add the type's schema name if
we want the transform name to be unique.

Not sure whether it's worth venturing into such nonlocal fixes.

            regards, tom lane

diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 5de3241eb4..2282c002ae 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -280,6 +280,34 @@ DOTypeNameCompare(const void *p1, const void *p2)
         if (cmpval != 0)
             return cmpval;
     }
+    else if (obj1->objType == DO_CONSTRAINT ||
+             obj1->objType == DO_FK_CONSTRAINT)
+    {
+        ConstraintInfo *cobj1 = *(ConstraintInfo *const *) p1;
+        ConstraintInfo *cobj2 = *(ConstraintInfo *const *) p2;
+        const char *objname1;
+        const char *objname2;
+
+        /* Sort by owning object name (namespace was considered already) */
+        if (cobj1->contable)
+            objname1 = cobj1->contable->dobj.name;
+        else if (cobj1->condomain)
+            objname1 = cobj1->condomain->dobj.name;
+        else
+            objname1 = NULL;
+        if (cobj2->contable)
+            objname2 = cobj2->contable->dobj.name;
+        else if (cobj2->condomain)
+            objname2 = cobj2->condomain->dobj.name;
+        else
+            objname2 = NULL;
+        if (objname1 && objname2)
+        {
+            cmpval = strcmp(objname1, objname2);
+            if (cmpval != 0)
+                return cmpval;
+        }
+    }
     else if (obj1->objType == DO_POLICY)
     {
         PolicyInfo *pobj1 = *(PolicyInfo *const *) p1;
@@ -291,6 +319,17 @@ DOTypeNameCompare(const void *p1, const void *p2)
         if (cmpval != 0)
             return cmpval;
     }
+    else if (obj1->objType == DO_RULE)
+    {
+        RuleInfo   *robj1 = *(RuleInfo *const *) p1;
+        RuleInfo   *robj2 = *(RuleInfo *const *) p2;
+
+        /* Sort by table name (table namespace was considered already) */
+        cmpval = strcmp(robj1->ruletable->dobj.name,
+                        robj2->ruletable->dobj.name);
+        if (cmpval != 0)
+            return cmpval;
+    }
     else if (obj1->objType == DO_TRIGGER)
     {
         TriggerInfo *tobj1 = *(TriggerInfo *const *) p1;
@@ -302,6 +341,39 @@ DOTypeNameCompare(const void *p1, const void *p2)
         if (cmpval != 0)
             return cmpval;
     }
+    else if (obj1->objType == DO_DEFAULT_ACL)
+    {
+        DefaultACLInfo *daclobj1 = *(DefaultACLInfo *const *) p1;
+        DefaultACLInfo *daclobj2 = *(DefaultACLInfo *const *) p2;
+
+        /* Sort by role name (objtype and namespace were considered already) */
+        cmpval = strcmp(daclobj1->defaclrole,
+                        daclobj2->defaclrole);
+        if (cmpval != 0)
+            return cmpval;
+    }
+    else if (obj1->objType == DO_PUBLICATION_REL)
+    {
+        PublicationRelInfo *probj1 = *(PublicationRelInfo *const *) p1;
+        PublicationRelInfo *probj2 = *(PublicationRelInfo *const *) p2;
+
+        /* Sort by publication name (table name/nsp was considered already) */
+        cmpval = strcmp(probj1->publication->dobj.name,
+                        probj2->publication->dobj.name);
+        if (cmpval != 0)
+            return cmpval;
+    }
+    else if (obj1->objType == DO_PUBLICATION_TABLE_IN_SCHEMA)
+    {
+        PublicationSchemaInfo *psobj1 = *(PublicationSchemaInfo *const *) p1;
+        PublicationSchemaInfo *psobj2 = *(PublicationSchemaInfo *const *) p2;
+
+        /* Sort by publication name (schema name was considered already) */
+        cmpval = strcmp(psobj1->publication->dobj.name,
+                        psobj2->publication->dobj.name);
+        if (cmpval != 0)
+            return cmpval;
+    }
 
     /* Usually shouldn't get here, but if we do, sort by OID */
     return oidcmp(obj1->catId.oid, obj2->catId.oid);

pgsql-general by date:

Previous
From: Adrian Klaver
Date:
Subject: Re: FK Constraint sort order with pg_dump
Next
From: Zsolt Ero
Date:
Subject: Re: could not link file in wal restore lines