Changeset: d10aa7212852 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d10aa7212852
Added Files:
        sql/test/group-concat/Tests/groupconcat05.sql
        sql/test/group-concat/Tests/groupconcat05.stable.err
        sql/test/group-concat/Tests/groupconcat05.stable.out
Modified Files:
        clients/Tests/MAL-signatures.stable.out
        clients/Tests/MAL-signatures.stable.out.int128
        clients/Tests/exports.stable.out
        gdk/gdk_aggr.c
        gdk/gdk_calc.h
        monetdb5/modules/kernel/aggr.c
        monetdb5/modules/kernel/aggr.mal
        monetdb5/modules/kernel/aggr.mal.sh
        monetdb5/modules/mal/01_calc.mal
        monetdb5/modules/mal/01_calc.mal.sh
        monetdb5/modules/mal/calc.c
        sql/ChangeLog
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_upgrades.c
        sql/scripts/51_sys_schema_extension.sql
        sql/test/Tests/systemfunctions.stable.out
        sql/test/Tests/systemfunctions.stable.out.int128
        sql/test/group-concat/Tests/All
        sql/test/group-concat/Tests/groupconcat01.stable.out
        sql/test/group-concat/Tests/groupconcat02.stable.out
        sql/test/group-concat/Tests/groupconcat03.sql
        sql/test/group-concat/Tests/groupconcat03.stable.out
        sql/test/group-concat/Tests/groupconcat04.stable.out
Branch: default
Log Message:

Implemented group_concat(X,Y) where Y is a string to be used as the separator 
in the result. Also fixed the implementation for empty strings.


diffs (truncated from 1314 to 300 lines):

diff --git a/clients/Tests/MAL-signatures.stable.out 
b/clients/Tests/MAL-signatures.stable.out
--- a/clients/Tests/MAL-signatures.stable.out
+++ b/clients/Tests/MAL-signatures.stable.out
@@ -205,10 +205,15 @@ Ready.
 [ "aggr",      "stdevp",       "command aggr.stdevp(b:bat[:sht], g:bat[:oid], 
e:bat[:any_1]):bat[:dbl] ",      "AGGRstdevp3_dbl;",     "Grouped tail standard 
deviation (population/biased) on sht"    ]
 [ "aggr",      "stdevp",       "command aggr.stdevp(b:bat[:any_2]):dbl ",      
"ALGstdevp;",   "Gives the standard deviation of all tail values"       ]
 [ "aggr",      "str_group_concat",     "command 
aggr.str_group_concat(b:bat[:str], g:bat[:oid], e:bat[:any_1]):bat[:str] ",    
"AGGRstr_group_concat;",        "Grouped string tail concat"    ]
+[ "aggr",      "str_group_concat",     "command 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], g:bat[:oid], 
e:bat[:any_1]):bat[:str] ",     "AGGRstr_group_concat_sep;",    "Grouped string 
tail concat with custom separator"      ]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str]):str ",      "CMDBATstr_group_concat;",      
"Calculate aggregate string concatenate of B."  ]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], nil_if_empty:bit):str ",    
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B."  
]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], s:bat[:oid]):str ", 
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with candidate list."      ]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], s:bat[:oid], nil_if_empty:bit):str ",       
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with candidate list."      ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str]):str ",       
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with separator SEP."       ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], nil_if_empty:bit):str ",     
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with separator SEP."       ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], s:bat[:oid]):str ",  
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with candidate list and separator SEP."    ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], s:bat[:oid], 
nil_if_empty:bit):str ",        "CMDBATstr_group_concat;",      "Calculate 
aggregate string concatenate of B with candidate list and separator SEP."    ]
 [ "aggr",      "subavg",       "command aggr.subavg(b:bat[:bte], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubavg1_dbl;",     "Grouped average aggregate"     ]
 [ "aggr",      "subavg",       "command aggr.subavg(b:bat[:dbl], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubavg1_dbl;",     "Grouped average aggregate"     ]
 [ "aggr",      "subavg",       "command aggr.subavg(b:bat[:flt], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubavg1_dbl;",     "Grouped average aggregate"     ]
@@ -316,7 +321,9 @@ Ready.
 [ "aggr",      "substdevp",    "command aggr.substdevp(b:bat[:lng], 
g:bat[:oid], e:bat[:any_1], s:bat[:oid], skip_nils:bit, 
abort_on_error:bit):bat[:dbl] ",   "AGGRsubstdevpcand_dbl;",       "Grouped 
standard deviation (population/biased) aggregate with candidates list" ]
 [ "aggr",      "substdevp",    "command aggr.substdevp(b:bat[:sht], 
g:bat[:oid], e:bat[:any_1], s:bat[:oid], skip_nils:bit, 
abort_on_error:bit):bat[:dbl] ",   "AGGRsubstdevpcand_dbl;",       "Grouped 
standard deviation (population/biased) aggregate with candidates list" ]
 [ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], g:bat[:oid], e:bat[:any_1], 
skip_nils:bit, abort_on_error:bit):bat[:str] ",      
"AGGRsubstr_group_concat;",     "Grouped string concat" ]
+[ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], sep:bat[:str], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:str] ",       
"AGGRsubstr_group_concat_sep;", "Grouped string concat with custom separator"   
]
 [ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], g:bat[:oid], e:bat[:any_1], s:bat[:oid], 
skip_nils:bit, abort_on_error:bit):bat[:str] ", "AGGRsubstr_group_concatcand;", 
"Grouped string concat with candidates list"    ]
+[ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], sep:bat[:str], g:bat[:oid], 
e:bat[:any_1], s:bat[:oid], skip_nils:bit, abort_on_error:bit):bat[:str] ",  
"AGGRsubstr_group_concatcand_sep;",     "Grouped string concat with candidates 
list with custom separator"      ]
 [ "aggr",      "subsum",       "command aggr.subsum(b:bat[:bte], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:bte] ",   
"AGGRsubsum_bte;",      "Grouped sum aggregate" ]
 [ "aggr",      "subsum",       "command aggr.subsum(b:bat[:dbl], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubsum_dbl;",      "Grouped sum aggregate" ]
 [ "aggr",      "subsum",       "command aggr.subsum(b:bat[:flt], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubsum_dbl;",      "Grouped sum aggregate" ]
diff --git a/clients/Tests/MAL-signatures.stable.out.int128 
b/clients/Tests/MAL-signatures.stable.out.int128
--- a/clients/Tests/MAL-signatures.stable.out.int128
+++ b/clients/Tests/MAL-signatures.stable.out.int128
@@ -244,10 +244,15 @@ Ready.
 [ "aggr",      "stdevp",       "command aggr.stdevp(b:bat[:sht], g:bat[:oid], 
e:bat[:any_1]):bat[:dbl] ",      "AGGRstdevp3_dbl;",     "Grouped tail standard 
deviation (population/biased) on sht"    ]
 [ "aggr",      "stdevp",       "command aggr.stdevp(b:bat[:any_2]):dbl ",      
"ALGstdevp;",   "Gives the standard deviation of all tail values"       ]
 [ "aggr",      "str_group_concat",     "command 
aggr.str_group_concat(b:bat[:str], g:bat[:oid], e:bat[:any_1]):bat[:str] ",    
"AGGRstr_group_concat;",        "Grouped string tail concat"    ]
+[ "aggr",      "str_group_concat",     "command 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], g:bat[:oid], 
e:bat[:any_1]):bat[:str] ",     "AGGRstr_group_concat_sep;",    "Grouped string 
tail concat with custom separator"      ]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str]):str ",      "CMDBATstr_group_concat;",      
"Calculate aggregate string concatenate of B."  ]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], nil_if_empty:bit):str ",    
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B."  
]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], s:bat[:oid]):str ", 
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with candidate list."      ]
 [ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], s:bat[:oid], nil_if_empty:bit):str ",       
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with candidate list."      ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str]):str ",       
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with separator SEP."       ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], nil_if_empty:bit):str ",     
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with separator SEP."       ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], s:bat[:oid]):str ",  
"CMDBATstr_group_concat;",      "Calculate aggregate string concatenate of B 
with candidate list and separator SEP."    ]
+[ "aggr",      "str_group_concat",     "pattern 
aggr.str_group_concat(b:bat[:str], sep:bat[:str], s:bat[:oid], 
nil_if_empty:bit):str ",        "CMDBATstr_group_concat;",      "Calculate 
aggregate string concatenate of B with candidate list and separator SEP."    ]
 [ "aggr",      "subavg",       "command aggr.subavg(b:bat[:bte], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubavg1_dbl;",     "Grouped average aggregate"     ]
 [ "aggr",      "subavg",       "command aggr.subavg(b:bat[:dbl], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubavg1_dbl;",     "Grouped average aggregate"     ]
 [ "aggr",      "subavg",       "command aggr.subavg(b:bat[:flt], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubavg1_dbl;",     "Grouped average aggregate"     ]
@@ -375,7 +380,9 @@ Ready.
 [ "aggr",      "substdevp",    "command aggr.substdevp(b:bat[:lng], 
g:bat[:oid], e:bat[:any_1], s:bat[:oid], skip_nils:bit, 
abort_on_error:bit):bat[:dbl] ",   "AGGRsubstdevpcand_dbl;",       "Grouped 
standard deviation (population/biased) aggregate with candidates list" ]
 [ "aggr",      "substdevp",    "command aggr.substdevp(b:bat[:sht], 
g:bat[:oid], e:bat[:any_1], s:bat[:oid], skip_nils:bit, 
abort_on_error:bit):bat[:dbl] ",   "AGGRsubstdevpcand_dbl;",       "Grouped 
standard deviation (population/biased) aggregate with candidates list" ]
 [ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], g:bat[:oid], e:bat[:any_1], 
skip_nils:bit, abort_on_error:bit):bat[:str] ",      
"AGGRsubstr_group_concat;",     "Grouped string concat" ]
+[ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], sep:bat[:str], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:str] ",       
"AGGRsubstr_group_concat_sep;", "Grouped string concat with custom separator"   
]
 [ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], g:bat[:oid], e:bat[:any_1], s:bat[:oid], 
skip_nils:bit, abort_on_error:bit):bat[:str] ", "AGGRsubstr_group_concatcand;", 
"Grouped string concat with candidates list"    ]
+[ "aggr",      "substr_group_concat",  "command 
aggr.substr_group_concat(b:bat[:str], sep:bat[:str], g:bat[:oid], 
e:bat[:any_1], s:bat[:oid], skip_nils:bit, abort_on_error:bit):bat[:str] ",  
"AGGRsubstr_group_concatcand_sep;",     "Grouped string concat with candidates 
list with custom separator"      ]
 [ "aggr",      "subsum",       "command aggr.subsum(b:bat[:bte], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:bte] ",   
"AGGRsubsum_bte;",      "Grouped sum aggregate" ]
 [ "aggr",      "subsum",       "command aggr.subsum(b:bat[:dbl], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubsum_dbl;",      "Grouped sum aggregate" ]
 [ "aggr",      "subsum",       "command aggr.subsum(b:bat[:flt], g:bat[:oid], 
e:bat[:any_1], skip_nils:bit, abort_on_error:bit):bat[:dbl] ",   
"AGGRsubsum_dbl;",      "Grouped sum aggregate" ]
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -131,7 +131,7 @@ BAT *BATgroupquantile(BAT *b, BAT *g, BA
 BAT *BATgroupsize(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int skip_nils, int 
abort_on_error);
 BAT *BATgroupstdev_population(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int 
skip_nils, int abort_on_error);
 BAT *BATgroupstdev_sample(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int 
skip_nils, int abort_on_error);
-BAT *BATgroupstr_group_concat(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int 
skip_nils, int abort_on_error);
+BAT *BATgroupstr_group_concat(BAT *b, BAT *g, BAT *e, BAT *s, int skip_nils, 
int abort_on_error, const str separator);
 BAT *BATgroupsum(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int skip_nils, int 
abort_on_error);
 BAT *BATgroupvariance_population(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int 
skip_nils, int abort_on_error);
 BAT *BATgroupvariance_sample(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int 
skip_nils, int abort_on_error);
@@ -170,7 +170,7 @@ void BATsetcount(BAT *b, BUN cnt);
 void BATsetprop(BAT *b, int idx, int type, void *v);
 BAT *BATslice(BAT *b, BUN low, BUN high);
 gdk_return BATsort(BAT **sorted, BAT **order, BAT **groups, BAT *b, BAT *o, 
BAT *g, int reverse, int stable) __attribute__((__warn_unused_result__));
-gdk_return BATstr_group_concat(ValPtr res, BAT *b, BAT *s, int skip_nils, int 
abort_on_error, int nil_if_empty);
+gdk_return BATstr_group_concat(ValPtr res, BAT *b, BAT *s, int skip_nils, int 
abort_on_error, int nil_if_empty, const str separator);
 gdk_return BATsubcross(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr) 
__attribute__((__warn_unused_result__));
 gdk_return BATsum(void *res, int tp, BAT *b, BAT *s, int skip_nils, int 
abort_on_error, int nil_if_empty);
 gdk_return BATthetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT 
*sr, int op, int nil_matches, BUN estimate) 
__attribute__((__warn_unused_result__));
@@ -608,6 +608,7 @@ str AGGRquantile3(bat *retval, const bat
 str AGGRstdev3_dbl(bat *retval, const bat *bid, const bat *gid, const bat 
*eid);
 str AGGRstdevp3_dbl(bat *retval, const bat *bid, const bat *gid, const bat 
*eid);
 str AGGRstr_group_concat(bat *retval, const bat *bid, const bat *gid, const 
bat *eid);
+str AGGRstr_group_concat_sep(bat *retval, const bat *bid, const bat *sepp, 
const bat *gid, const bat *eid);
 str AGGRsubavg1_dbl(bat *retval, const bat *bid, const bat *gid, const bat 
*eid, const bit *skip_nils, const bit *abort_on_error);
 str AGGRsubavg1cand_dbl(bat *retval, const bat *bid, const bat *gid, const bat 
*eid, const bat *sid, const bit *skip_nils, const bit *abort_on_error);
 str AGGRsubavg2_dbl(bat *retval1, bat *retval2, const bat *bid, const bat 
*gid, const bat *eid, const bit *skip_nils, const bit *abort_on_error);
@@ -645,7 +646,9 @@ str AGGRsubstdevcand_dbl(bat *retval, co
 str AGGRsubstdevp_dbl(bat *retval, const bat *bid, const bat *gid, const bat 
*eid, const bit *skip_nils, const bit *abort_on_error);
 str AGGRsubstdevpcand_dbl(bat *retval, const bat *bid, const bat *gid, const 
bat *eid, const bat *sid, const bit *skip_nils, const bit *abort_on_error);
 str AGGRsubstr_group_concat(bat *retval, const bat *bid, const bat *gid, const 
bat *eid, const bit *skip_nils, const bit *abort_on_error);
+str AGGRsubstr_group_concat_sep(bat *retval, const bat *bid, const bat *sepp, 
const bat *gid, const bat *eid, const bit *skip_nils, const bit 
*abort_on_error);
 str AGGRsubstr_group_concatcand(bat *retval, const bat *bid, const bat *gid, 
const bat *eid, const bat *sid, const bit *skip_nils, const bit 
*abort_on_error);
+str AGGRsubstr_group_concatcand_sep(bat *retval, const bat *bid, const bat 
*sepp, const bat *gid, const bat *eid, const bat *sid, const bit *skip_nils, 
const bit *abort_on_error);
 str AGGRsubsum_bte(bat *retval, const bat *bid, const bat *gid, const bat 
*eid, const bit *skip_nils, const bit *abort_on_error);
 str AGGRsubsum_dbl(bat *retval, const bat *bid, const bat *gid, const bat 
*eid, const bit *skip_nils, const bit *abort_on_error);
 str AGGRsubsum_flt(bat *retval, const bat *bid, const bat *gid, const bat 
*eid, const bit *skip_nils, const bit *abort_on_error);
diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -3265,13 +3265,12 @@ BATgroupvariance_population(BAT *b, BAT 
 
 static gdk_return
 concat_strings(void *res, int what, BAT* b, int nonil, oid seqb, BUN start, 
BUN end, BUN ngrp, const oid *restrict cand,
-                          const oid *candend, const oid *restrict gids, oid 
min, oid max, int skip_nils, const char *func,
-                          BUN *has_nils)
+                          const oid *candend, const oid *restrict gids, oid 
min, oid max, int skip_nils, const str separator,
+                          const char *func, BUN *has_nils)
 {
        oid gid;
        BUN i, p, q, nils = 0;
        const oid *aux;
-       const char *separator = ",";
        size_t* lengths = NULL, separator_length = strlen(separator), 
next_length;
        oid *lastoid = NULL;
        str* astrings = NULL, s, single_str = NULL;
@@ -3296,20 +3295,16 @@ concat_strings(void *res, int what, BAT*
                                BATloop(b,p,q) {
                                        s = BUNtail(bi, p);
                                        next_length = strlen(s);
-                                       if(next_length) {
-                                               single_length += next_length + 
separator_length;
-                                               single_oid = p;
-                                       }
+                                       single_length += next_length + 
separator_length;
+                                       single_oid = p;
                                }
                        } else {
                                BATloop(b,p,q) {
                                        s = BUNtail(bi, p);
                                        if (strcmp(s, str_nil)) {
                                                next_length = strlen(s);
-                                               if(next_length) {
-                                                       single_length += 
next_length + separator_length;
-                                                       single_oid = p;
-                                               }
+                                               single_length += next_length + 
separator_length;
+                                               single_oid = p;
                                        } else {
                                                single_oid = BUN_NONE;
                                                nils = 1;
@@ -3318,50 +3313,32 @@ concat_strings(void *res, int what, BAT*
                                }
                        }
                        if(!nils) {
-                               if(single_length > 0) {
-                                       if ((single_str = 
GDKmalloc((single_length + 1 - separator_length) * sizeof(str))) == NULL) {
-                                               GDKerror("%s: malloc 
failure\n", func);
-                                               rres = GDK_FAIL;
-                                               goto finish;
-                                       }
-                                       BATloop(b,p,q){
-                                               s = BUNtail(bi, p);
-                                               next_length = strlen(s);
-                                               if(next_length) {
-                                                       memcpy(single_str + 
offset, s, next_length);
-                                                       offset += next_length;
-                                                       if(p != single_oid) {
-                                                               
memcpy(single_str + offset, separator, separator_length);
-                                                               offset += 
separator_length;
-                                                       }
-                                               }
+                               if ((single_str = GDKmalloc((single_length + 1 
- separator_length) * sizeof(str))) == NULL) {
+                                       GDKerror("%s: malloc failure\n", func);
+                                       rres = GDK_FAIL;
+                                       goto finish;
+                               }
+                               BATloop(b,p,q){
+                                       s = BUNtail(bi, p);
+                                       next_length = strlen(s);
+                                       memcpy(single_str + offset, s, 
next_length);
+                                       offset += next_length;
+                                       if(p != single_oid) {
+                                               memcpy(single_str + offset, 
separator, separator_length);
+                                               offset += separator_length;
                                        }
-                                       single_str[offset] = '\0';
-                                       if(what == IS_A_BAT) {
-                                               if(BUNappend(bn, single_str, 
FALSE) != GDK_SUCCEED) {
-                                                       GDKerror("%s: malloc 
failure\n", func);
-                                                       rres = GDK_FAIL;
-                                                       goto finish;
-                                               }
-                                       } else {
-                                               ValPtr pt = (ValPtr) res;
-                                               pt->len = single_str[offset];
-                                               if((pt->val.sval = 
GDKstrdup(single_str)) == NULL) {
-                                                       GDKerror("%s: malloc 
failure\n", func);
-                                                       rres = GDK_FAIL;
-                                                       goto finish;
-                                               }
-                                       }
-                               } else if(what == IS_A_BAT) {
-                                       if(BUNappend(bn, "", FALSE) != 
GDK_SUCCEED) {
+                               }
+                               single_str[offset] = '\0';
+                               if(what == IS_A_BAT) {
+                                       if(BUNappend(bn, single_str, FALSE) != 
GDK_SUCCEED) {
                                                GDKerror("%s: malloc 
failure\n", func);
                                                rres = GDK_FAIL;
                                                goto finish;
                                        }
                                } else {
                                        ValPtr pt = (ValPtr) res;
-                                       pt->len = 0;
-                                       if((pt->val.sval = GDKstrdup("")) == 
NULL) {
+                                       pt->len = single_str[offset];
+                                       if((pt->val.sval = 
GDKstrdup(single_str)) == NULL) {
                                                GDKerror("%s: malloc 
failure\n", func);
                                                rres = GDK_FAIL;
                                                goto finish;
@@ -3391,10 +3368,8 @@ concat_strings(void *res, int what, BAT*
                                                break;
                                        s = BUNtail(bi, i);
                                        next_length = strlen(s);
-                                       if(next_length > 0) {
-                                               single_length += next_length + 
separator_length;
-                                               single_oid = i;
-                                       }
+                                       single_length += next_length + 
separator_length;
+                                       single_oid = i;
                                }
                        } else {
                                while (cand < candend && nils == 0) {
@@ -3404,10 +3379,8 @@ concat_strings(void *res, int what, BAT*
                                        s = BUNtail(bi, i);
                                        if (strcmp(s, str_nil)) {
                                                next_length = strlen(s);
-                                               if(next_length > 0) {
-                                                       single_length += 
next_length + separator_length;
-                                                       single_oid = i;
-                                               }
+                                               single_length += next_length + 
separator_length;
+                                               single_oid = i;
                                        } else {
                                                single_oid = BUN_NONE;
                                                nils = 1;
@@ -3416,35 +3389,27 @@ concat_strings(void *res, int what, BAT*
                                }
                        }
                        if (!nils) {
-                               if(single_length > 0) {
-                                       if ((single_str = 
GDKmalloc((single_length + 1 - separator_length) * sizeof(str))) == NULL) {
-                                               GDKerror("%s: malloc 
failure\n", func);
-                                               rres = GDK_FAIL;
-                                               goto finish;
+                               if ((single_str = GDKmalloc((single_length + 1 
- separator_length) * sizeof(str))) == NULL) {
+                                       GDKerror("%s: malloc failure\n", func);
+                                       rres = GDK_FAIL;
+                                       goto finish;
+                               }
+                               cand = aux;
+                               while (cand < candend) {
+                                       i = *cand++ - seqb;
+                                       if (i >= end)
+                                               break;
+                                       s = BUNtail(bi, i);
+                                       next_length = strlen(s);
+                                       memcpy(single_str + offset, s, 
next_length);
+                                       offset += next_length;
+                                       if (i != single_oid) {
+                                               memcpy(single_str + offset, 
separator, separator_length);
+                                               offset += separator_length;
                                        }
-                                       cand = aux;
-                                       while (cand < candend) {
-                                               i = *cand++ - seqb;
-                                               if (i >= end)
-                                                       break;
-                                               s = BUNtail(bi, i);
-                                               next_length = strlen(s);
-                                               if(next_length > 0) {
-                                                       memcpy(single_str + 
offset, s, next_length);
-                                                       offset += next_length;
-                                                       if (i != single_oid) {
-                                                               
memcpy(single_str + offset, separator, separator_length);
-                                                               offset += 
separator_length;
-                                                       }
-                                               }
-                                       }
-                                       single_str[offset] = '\0';
-                                       if (BUNappend(bn, single_str, FALSE) != 
GDK_SUCCEED) {
-                                               GDKerror("%s: malloc 
failure\n", func);
-                                               rres = GDK_FAIL;
-                                               goto finish;
-                                       }
-                               } else if (BUNappend(bn, "", FALSE) != 
GDK_SUCCEED) {
+                               }
+                               single_str[offset] = '\0';
+                               if (BUNappend(bn, single_str, FALSE) != 
GDK_SUCCEED) {
                                        GDKerror("%s: malloc failure\n", func);
                                        rres = GDK_FAIL;
                                        goto finish;
@@ -3476,10 +3441,8 @@ concat_strings(void *res, int what, BAT*
                                                s = BUNtail(bi, i);
                                                if (strcmp(s, str_nil)) {
                                                        next_length = strlen(s);
-                                                       if(next_length > 0) {
-                                                               lengths[gid] += 
next_length + separator_length;
-                                                               lastoid[gid] = 
i;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to