Changeset: 8e99c6d33c7f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/8e99c6d33c7f
Modified Files:
        gdk/gdk_string.c
        sql/test/BugTracker-2026/Tests/All
Branch: default
Log Message:

Merge with Dec2025 branch.


diffs (truncated from 410 to 300 lines):

diff --git a/gdk/gdk_calc_private.h b/gdk/gdk_calc_private.h
--- a/gdk/gdk_calc_private.h
+++ b/gdk/gdk_calc_private.h
@@ -31,11 +31,11 @@
 
 #define GT(a, b)       ((bit) ((a) > (b)))
 
-#if !defined(__clang__) || __clang_major__ >= 21
-/* compiling with clang on Ubuntu 24.04 fails when using
- * __builtin_mul_overflow, so we avoid using it when using the version
- * of clang that is installed on said system (clang on Ubuntu 26.04 does
- * work) */
+#if defined(__aarch64__) && (!defined(__clang__) || __clang_major__ >= 21)
+/* compiling with clang on Ubuntu 24.04 on aarch64 (aka arm64) fails
+ * when using __builtin_mul_overflow, so we avoid using it when using
+ * the version of clang that is installed on said system (clang on
+ * Ubuntu 26.04 does work) */
 #ifdef __has_builtin
 #if __has_builtin(__builtin_add_overflow)
 #define OP_WITH_CHECK(lft, rgt, TYPE3, dst, op, max, on_overflow)      \
diff --git a/gdk/gdk_string.c b/gdk/gdk_string.c
--- a/gdk/gdk_string.c
+++ b/gdk/gdk_string.c
@@ -1099,6 +1099,7 @@ concat_strings(allocator *ma, BAT **bnp,
        assert((bnp == NULL) != (pt == NULL));
        /* if pt not NULL, only a single group allowed */
        assert(pt == NULL || ngrp == 1);
+       assert(separator == NULL || !strNil(separator));
 
        if (bnp) {
                if ((bn = COLnew(min, TYPE_str, ngrp, TRANSIENT)) == NULL) {
@@ -1147,15 +1148,8 @@ concat_strings(allocator *ma, BAT **bnp,
                                        }
                                } else {
                                        single_length += strlen(s);
-                                       if (!empty) {
-                                               if (strNil(sl)) {
-                                                       if (!skip_nils) {
-                                                               nils = 1;
-                                                               break;
-                                                       }
-                                               } else
-                                                       single_length += 
strlen(sl);
-                                       }
+                                       if (!empty && !strNil(sl))
+                                               single_length += strlen(sl);
                                        empty = false;
                                }
                        }
@@ -1285,13 +1279,11 @@ concat_strings(allocator *ma, BAT **bnp,
                                        if (lengths[gid] == (size_t) -1)
                                                continue;
                                        const char *s = BUNtvar(&bi, i);
-                                       const char *sl = BUNtvar(&bis, i);
                                        if (!strNil(s)) {
+                                               const char *sl = BUNtvar(&bis, 
i);
                                                lengths[gid] += strlen(s);
-                                               if (!strNil(sl)) {
-                                                       next_length = 
strlen(sl);
-                                                       lengths[gid] += 
next_length;
-                                               }
+                                               next_length = strNil(sl) ? 0 : 
strlen(sl);
+                                               lengths[gid] += next_length;
                                                astrings[gid] = NULL;
                                        } else if (!skip_nils) {
                                                nils++;
@@ -1357,13 +1349,15 @@ concat_strings(allocator *ma, BAT **bnp,
                                        gid = gids[i] - min;
                                        if (astrings[gid]) {
                                                const char *s = BUNtvar(&bi, i);
-                                               const char *sl = BUNtvar(&bis, 
i);
                                                if (strNil(s))
                                                        continue;
-                                               if (astrings[gid][lengths[gid]] 
&& !strNil(sl)) {
-                                                       next_length = 
strlen(sl);
-                                                       memcpy(astrings[gid] + 
lengths[gid], sl, next_length);
-                                                       lengths[gid] += 
next_length;
+                                               if 
(astrings[gid][lengths[gid]]) {
+                                                       const char *sl = 
BUNtvar(&bis, i);
+                                                       if (!strNil(sl)) {
+                                                               next_length = 
strlen(sl);
+                                                               
memcpy(astrings[gid] + lengths[gid], sl, next_length);
+                                                               lengths[gid] += 
next_length;
+                                                       }
                                                }
                                                next_length = strlen(s);
                                                memcpy(astrings[gid] + 
lengths[gid], s, next_length);
@@ -1413,20 +1407,21 @@ BATstr_group_concat(allocator *ma, ValPt
 {
        struct canditer ci;
        gdk_return r = GDK_SUCCEED;
-       const char *nseparator = separator;
-
-       assert((nseparator && !sep) || (!nseparator && sep)); /* only one of 
them must be set */
+
+       assert((separator && !sep) || (!separator && sep)); /* only one of them 
must be set */
        *res = (ValRecord) {.vtype = TYPE_str};
 
        canditer_init(&ci, b, s);
 
        BATiter bi = bat_iterator(sep);
        if (sep && BATcount(sep) == 1) { /* Only one element in sep */
-               nseparator = BUNtvar(&bi, 0);
+               separator = BUNtvar(&bi, 0);
                sep = NULL;
        }
-
-       if (ci.ncand == 0 || (nseparator && strNil(nseparator))) {
+       if (separator && strNil(separator))
+               separator = "";
+
+       if (ci.ncand == 0) {
                if (VALinit(ma, res, TYPE_str, nil_if_empty ? str_nil : "") == 
NULL)
                        r = GDK_FAIL;
                bat_iterator_end(&bi);
@@ -1434,7 +1429,7 @@ BATstr_group_concat(allocator *ma, ValPt
        }
 
        r = concat_strings(ma, NULL, res, b, b->hseqbase, 1, &ci, NULL, 0, 0,
-                             skip_nils, sep, nseparator, NULL);
+                             skip_nils, sep, separator, NULL);
        bat_iterator_end(&bi);
        return r;
 }
@@ -1449,9 +1444,8 @@ BATgroupstr_group_concat(BAT *b, BAT *g,
        struct canditer ci;
        const char *err;
        gdk_return res;
-       const char *nseparator = separator;
-
-       assert((nseparator && !sep) || (!nseparator && sep)); /* only one of 
them must be set */
+
+       assert((separator && !sep) || (!separator && sep)); /* only one of them 
must be set */
        (void) skip_nils;
 
        if ((err = BATgroupaggrinit(b, g, e, s, &min, &max, &ngrp,
@@ -1466,11 +1460,13 @@ BATgroupstr_group_concat(BAT *b, BAT *g,
 
        BATiter bi = bat_iterator(sep);
        if (sep && BATcount(sep) == 1) { /* Only one element in sep */
-               nseparator = BUNtvar(&bi, 0);
+               separator = BUNtvar(&bi, 0);
                sep = NULL;
        }
-
-       if (ci.ncand == 0 || ngrp == 0 || (nseparator && strNil(nseparator))) {
+       if (separator && strNil(separator))
+               separator = "";
+
+       if (ci.ncand == 0 || ngrp == 0) {
                /* trivial: no strings to concat, so return bat
                 * aligned with g with nil in the tail */
                bn = BATconstant(ngrp == 0 ? 0 : min, TYPE_str, str_nil, ngrp, 
TRANSIENT);
@@ -1488,7 +1484,7 @@ BATgroupstr_group_concat(BAT *b, BAT *g,
 
        res = concat_strings(NULL, &bn, NULL, b, b->hseqbase, ngrp, &ci,
                             (const oid *) Tloc(g, 0), min, max, skip_nils, sep,
-                            nseparator, &nils);
+                            separator, &nils);
        if (res != GDK_SUCCEED)
                bn = NULL;
 
@@ -1513,6 +1509,7 @@ compute_next_single_str(size_t *mglp, ch
        size_t next_length = 0;
        size_t offset = 0;
        bool empty = true;
+       assert(separator == NULL || !strNil(separator));
 
        for (oid m = start; m < end; m++) {
                const char *sb = BUNtvar(bi, m);
@@ -1623,9 +1620,11 @@ GDKanalytical_str_group_concat(BAT *b, B
                separator = BUNtvar(&sepi, 0);
                sep = NULL;
        }
-
-       if (sep == NULL)
+       if (separator) {
+               if (strNil(separator))
+                       separator = "";
                separator_length = strlen(separator);
+       }
 
        if ((bn = COLnew(b->hseqbase, TYPE_str, bi.count, TRANSIENT)) == NULL)
                goto bailout;
diff --git 
a/sql/test/BugTracker-2026/Tests/7976-dump_database-composite-key-order-bug.test
 
b/sql/test/BugTracker-2026/Tests/7976-dump_database-composite-key-order-bug.test
new file mode 100644
--- /dev/null
+++ 
b/sql/test/BugTracker-2026/Tests/7976-dump_database-composite-key-order-bug.test
@@ -0,0 +1,108 @@
+statement ok
+CREATE SCHEMA demo
+
+statement ok
+SET SCHEMA demo
+
+statement ok
+CREATE TABLE parent (
+    a INT NOT NULL,
+    b INT NOT NULL,
+    CONSTRAINT parent_ab UNIQUE (a, b)
+)
+
+statement ok
+CREATE TABLE child (
+    a INT NOT NULL,
+    b INT NOT NULL,
+    CONSTRAINT child_fk
+        FOREIGN KEY (a, b) REFERENCES parent (a, b)
+)
+
+query IT rowsort
+SELECT o.nr, o.name
+FROM sys.objects o
+JOIN sys.keys k ON o.id = k.id
+JOIN sys._tables t ON k.table_id = t.id
+JOIN sys.schemas s ON t.schema_id = s.id
+WHERE s.name = 'demo'
+  AND t.name = 'parent'
+  AND k.type = 1
+ORDER BY o.nr
+----
+0
+a
+1
+b
+
+query T nosort
+SELECT stmt
+FROM sys.dump_table_constraint_type
+WHERE schema_name = 'demo'
+  AND table_name = 'parent'
+----
+ALTER TABLE "demo"."parent" ADD CONSTRAINT "parent_ab" UNIQUE ("a", "b");
+
+statement ok
+CREATE SCHEMA noise
+
+statement ok
+CREATE TABLE noise.unrelated (
+    a INT NOT NULL,
+    b INT NOT NULL,
+    UNIQUE (a, b)
+)
+
+-- The catalogue query still returns 0, a and 1, b
+query IT rowsort
+SELECT o.nr, o.name
+FROM sys.objects o
+JOIN sys.keys k ON o.id = k.id
+JOIN sys._tables t ON k.table_id = t.id
+JOIN sys.schemas s ON t.schema_id = s.id
+WHERE s.name = 'demo'
+  AND t.name = 'parent'
+  AND k.type = 1
+ORDER BY o.nr
+----
+0
+a
+1
+b
+
+-- but the dump query now returns: ALTER TABLE "demo"."parent" ADD CONSTRAINT 
"parent_ab" UNIQUE ("b", "a"); -- key columns are reversed
+query T nosort
+SELECT stmt
+FROM sys.dump_table_constraint_type
+WHERE schema_name = 'demo'
+  AND table_name = 'parent'
+----
+ALTER TABLE "demo"."parent" ADD CONSTRAINT "parent_ab" UNIQUE ("a", "b");
+
+query T nosort
+SELECT stmt
+FROM sys.dump_database(TRUE)
+WHERE stmt LIKE 'ALTER TABLE "demo".%'
+ORDER BY o
+----
+ALTER TABLE "demo"."parent" ADD CONSTRAINT "parent_ab" UNIQUE ("a", "b");
+ALTER TABLE "demo"."child" ADD CONSTRAINT "child_fk" FOREIGN KEY("a","b") 
REFERENCES "demo"."parent"("a","b") ON DELETE RESTRICT ON UPDATE RESTRICT;
+
+statement ok
+DROP SCHEMA noise CASCADE
+
+-- the dump query now returns: ALTER TABLE "demo"."parent" ADD CONSTRAINT 
"parent_ab" UNIQUE ("a", "b");
+query T nosort
+SELECT stmt
+FROM sys.dump_table_constraint_type
+WHERE schema_name = 'demo'
+  AND table_name = 'parent'
+----
+ALTER TABLE "demo"."parent" ADD CONSTRAINT "parent_ab" UNIQUE ("a", "b");
+
+statement ok
+SET SCHEMA sys
+
+statement ok
+DROP SCHEMA demo CASCADE
+
diff --git 
a/sql/test/BugTracker-2026/Tests/7985-qualify-row_number-over-bug.test 
b/sql/test/BugTracker-2026/Tests/7985-qualify-row_number-over-bug.test
new file mode 100644
--- /dev/null
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to