Changeset: c0a570e86ae2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c0a570e86ae2
Modified Files:
        gdk/gdk_string.c
Branch: Dec2025
Log Message:

In group_concat, consistently treat a NULL separator as an empty string.
This fixes #7991.  It also align better with postgresql


diffs (164 lines):

diff --git a/gdk/gdk_string.c b/gdk/gdk_string.c
--- a/gdk/gdk_string.c
+++ b/gdk/gdk_string.c
@@ -827,6 +827,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) {
@@ -875,15 +876,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;
                                }
                        }
@@ -1013,13 +1007,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++;
@@ -1085,13 +1077,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);
@@ -1141,20 +1135,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);
@@ -1162,7 +1157,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;
 }
@@ -1177,9 +1172,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,
@@ -1194,11 +1188,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);
@@ -1216,7 +1212,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;
 
@@ -1241,6 +1237,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);
@@ -1350,9 +1347,11 @@ GDKanalytical_str_group_concat(BAT *r, B
                separator = BUNtvar(sepi, 0);
                sep = NULL;
        }
-
-       if (sep == NULL)
+       if (separator) {
+               if (strNil(separator))
+                       separator = "";
                separator_length = strlen(separator);
+       }
 
        if (bi.count > 0) {
                switch (frame_type) {
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to