]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Dump labels in reproducible order
authorPeter Eisentraut <peter@eisentraut.org>
Tue, 17 Mar 2026 13:06:53 +0000 (14:06 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Tue, 17 Mar 2026 13:07:29 +0000 (14:07 +0100)
In pg_get_propgraphdef(), sort the labels before writing out, for a
consistent dump order.  Also, since we now have a list, we can get rid
of the separate table scan to get the count.

Co-authored-by: Peter Eisentraut <peter@eisentraut.org>
Co-authored-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Co-authored-by: Andrew Dunstan <andrew@dunslane.net>
Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/a855795d-e697-4fa5-8698-d20122126567@eisentraut.org

src/backend/utils/adt/ruleutils.c

index 153a92fd3eaf71b168a25562db0a1ee7aa50ac5b..7bc12589e40e64c65fbe1ce9fe98a947a8509e27 100644 (file)
@@ -1772,6 +1772,21 @@ make_propgraphdef_elements(StringInfo buf, Oid pgrelid, char pgekind)
        table_close(pgerel, AccessShareLock);
 }
 
+struct oid_str_pair
+{
+       Oid                     oid;
+       char       *str;
+};
+
+static int
+list_oid_str_pair_cmp_by_str(const ListCell *p1, const ListCell *p2)
+{
+       struct oid_str_pair *v1 = lfirst(p1);
+       struct oid_str_pair *v2 = lfirst(p2);
+
+       return strcmp(v1->str, v2->str);
+}
+
 /*
  * Generates label and properties list.  Pass in the element OID, the element
  * alias, and the graph relation OID.  Result is appended to buf.
@@ -1784,6 +1799,7 @@ make_propgraphdef_labels(StringInfo buf, Oid elid, const char *elalias, Oid elre
        SysScanDesc scan;
        int                     count;
        HeapTuple       tup;
+       List       *label_list = NIL;
 
        pglrel = table_open(PropgraphElementLabelRelationId, AccessShareLock);
 
@@ -1792,38 +1808,51 @@ make_propgraphdef_labels(StringInfo buf, Oid elid, const char *elalias, Oid elre
                                BTEqualStrategyNumber, F_OIDEQ,
                                ObjectIdGetDatum(elid));
 
-       count = 0;
+       /*
+        * We want to output the labels in a deterministic order.  So we first
+        * read all the data, then sort, then print it.
+        */
        scan = systable_beginscan(pglrel, PropgraphElementLabelElementLabelIndexId, true, NULL, 1, scankey);
+
        while ((tup = systable_getnext(scan)))
        {
-               count++;
+               Form_pg_propgraph_element_label pgelform = (Form_pg_propgraph_element_label) GETSTRUCT(tup);
+               struct oid_str_pair *osp;
+
+               osp = palloc_object(struct oid_str_pair);
+               osp->oid = pgelform->oid;
+               osp->str = get_propgraph_label_name(pgelform->pgellabelid);
+
+               label_list = lappend(label_list, osp);
        }
+
        systable_endscan(scan);
+       table_close(pglrel, AccessShareLock);
 
-       scan = systable_beginscan(pglrel, PropgraphElementLabelElementLabelIndexId, true, NULL, 1, scankey);
+       count = list_length(label_list);
 
-       while ((tup = systable_getnext(scan)))
-       {
-               Form_pg_propgraph_element_label pgelform = (Form_pg_propgraph_element_label) GETSTRUCT(tup);
-               const char *labelname;
+       /* Each element has at least one label. */
+       Assert(count > 0);
 
-               labelname = get_propgraph_label_name(pgelform->pgellabelid);
+       /*
+        * It is enough for the comparison function to compare just labels, since
+        * all the labels of an element table should have distinct names.
+        */
+       list_sort(label_list, list_oid_str_pair_cmp_by_str);
 
-               if (strcmp(labelname, elalias) == 0)
+       foreach_ptr(struct oid_str_pair, osp, label_list)
+       {
+               if (strcmp(osp->str, elalias) == 0)
                {
                        /* If the default label is the only label, don't print anything. */
                        if (count != 1)
                                appendStringInfo(buf, " DEFAULT LABEL");
                }
                else
-                       appendStringInfo(buf, " LABEL %s", quote_identifier(labelname));
+                       appendStringInfo(buf, " LABEL %s", quote_identifier(osp->str));
 
-               make_propgraphdef_properties(buf, pgelform->oid, elrelid);
+               make_propgraphdef_properties(buf, osp->oid, elrelid);
        }
-
-       systable_endscan(scan);
-
-       table_close(pglrel, AccessShareLock);
 }
 
 /*