LCOV - code coverage report
Current view: top level - monetdb5/modules/kernel - batstr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 981 2954 33.2 %
Date: 2021-10-13 02:24:04 Functions: 69 112 61.6 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  *  M.L. Kersten
      11             :  * String multiplexes
      12             :  * [TODO: property propagations]
      13             :  * The collection of routines provided here are map operations
      14             :  * for the atom string primitives.
      15             :  *
      16             :  * In line with the batcalc module, we assume that if two bat operands
      17             :  * are provided that they are aligned.
      18             :  */
      19             : #include "monetdb_config.h"
      20             : #include "gdk.h"
      21             : #include <ctype.h>
      22             : #include <string.h>
      23             : #include "mal_client.h"
      24             : #include "mal_interpreter.h"
      25             : #include "mal_exception.h"
      26             : #include "str.h"
      27             : 
      28             : /* In order to make avaialble a bulk version of a string function with candidates, all possible combinations of scalar/vector
      29             :         version of each argument must be avaiable for the function. Obviously this won't scale for functions with a large number of
      30             :         arguments, so we keep a blacklist for functions without candidate versions. */
      31             : static const char* batstr_funcs_with_no_cands[8] = {"lpad3","rpad3","splitpart","substitute","locate3","insert","replace",NULL};
      32             : 
      33             : bool
      34         306 : batstr_func_has_candidates(const char *func)
      35             : {
      36        2434 :         for (size_t i = 0; batstr_funcs_with_no_cands[i]; i++)
      37        2140 :                 if (strcmp(batstr_funcs_with_no_cands[i], func) == 0)
      38             :                         return false;
      39             :         return true;
      40             : }
      41             : 
      42             : static void
      43        5851 : finalize_ouput(bat *res, BAT *bn, str msg, bool nils, BUN q)
      44             : {
      45        5851 :         if (bn && !msg) {
      46        5851 :                 BATsetcount(bn, q);
      47        5853 :                 bn->tnil = nils;
      48        5853 :                 bn->tnonil = !nils;
      49        5853 :                 bn->tkey = BATcount(bn) <= 1;
      50        5853 :                 bn->tsorted = BATcount(bn) <= 1;
      51        5853 :                 bn->trevsorted = BATcount(bn) <= 1;
      52        5853 :                 BBPkeepref(*res = bn->batCacheid);
      53           0 :         } else if (bn)
      54           0 :                 BBPreclaim(bn);
      55        5853 : }
      56             : 
      57             : static void
      58        5853 : unfix_inputs(int nargs, ...)
      59             : {
      60             :         va_list valist;
      61             : 
      62        5853 :         va_start(valist, nargs);
      63       17671 :         for (int i = 0; i < nargs; i++) {
      64       11818 :                 BAT *b = va_arg(valist, BAT *);
      65       11818 :                 if (b)
      66        6157 :                         BBPunfix(b->batCacheid);
      67             :         }
      68        5853 :         va_end(valist);
      69        5853 : }
      70             : 
      71             : static inline str
      72      162513 : str_prefix(str *buf, size_t *buflen, str s, int l)
      73             : {
      74      162513 :         return str_Sub_String(buf, buflen, s, 0, l);
      75             : }
      76             : 
      77             : static str
      78        5004 : do_batstr_int(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, int (*func)(const char *restrict))
      79             : {
      80             :         BATiter bi;
      81             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
      82             :         BUN q = 0;
      83             :         int *restrict vals;
      84             :         str x, msg = MAL_SUCCEED;
      85             :         bool nils = false;
      86        5004 :         struct canditer ci1 = {0};
      87             :         oid off1;
      88        5004 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
      89        5004 :                 *sid1 = pci->argc == 3 ? getArgReference_bat(stk, pci, 2) : NULL;
      90             : 
      91             :         (void) cntxt;
      92             :         (void) mb;
      93        5004 :         if (!(b = BATdescriptor(*bid))) {
      94           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      95           0 :                 goto bailout;
      96             :         }
      97        5004 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
      98           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      99           0 :                 goto bailout;
     100             :         }
     101        5004 :         q = canditer_init(&ci1, b, bs);
     102        5004 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
     103           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     104           0 :                 goto bailout;
     105             :         }
     106             : 
     107        5004 :         off1 = b->hseqbase;
     108        5004 :         bi = bat_iterator(b);
     109        5004 :         vals = Tloc(bn, 0);
     110        5004 :         if (ci1.tpe == cand_dense) {
     111     2500010 :                 for (BUN i = 0; i < q; i++) {
     112     2495072 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     113     2495072 :                         x = (str) BUNtvar(bi, p1);
     114             : 
     115     2495072 :                         if (strNil(x)) {
     116           0 :                                 vals[i] = int_nil;
     117             :                                 nils = true;
     118             :                         } else {
     119     2495072 :                                 vals[i] = func(x);
     120             :                         }
     121             :                 }
     122             :         } else {
     123     1933607 :                 for (BUN i = 0; i < q; i++) {
     124     1933543 :                         oid p1 = (canditer_next(&ci1) - off1);
     125     1933099 :                         x = (str) BUNtvar(bi, p1);
     126             : 
     127     1933099 :                         if (strNil(x)) {
     128           0 :                                 vals[i] = int_nil;
     129             :                                 nils = true;
     130             :                         } else {
     131     1933099 :                                 vals[i] = func(x);
     132             :                         }
     133             :                 }
     134             :         }
     135        5002 :         bat_iterator_end(&bi);
     136        5004 : bailout:
     137        5004 :         finalize_ouput(res, bn, msg, nils, q);
     138        5004 :         unfix_inputs(2, b, bs);
     139        5004 :         return msg;
     140             : }
     141             : 
     142             : static str
     143        5003 : STRbatLength(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     144             : {
     145        5003 :         return do_batstr_int(cntxt, mb, stk, pci, "batstr.length", UTF8_strlen);
     146             : }
     147             : 
     148             : static str
     149           1 : STRbatBytes(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     150             : {
     151           1 :         return do_batstr_int(cntxt, mb, stk, pci, "batstr.bytes", str_strlen);
     152             : }
     153             : 
     154             : static str
     155           3 : STRbatAscii(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     156             : {
     157             :         BATiter bi;
     158             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     159             :         BUN q = 0;
     160             :         int *restrict vals, next;
     161             :         str x, msg = MAL_SUCCEED;
     162             :         bool nils = false;
     163           3 :         struct canditer ci1 = {0};
     164             :         oid off1;
     165           3 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     166           3 :                 *sid1 = pci->argc == 3 ? getArgReference_bat(stk, pci, 2) : NULL;
     167             : 
     168             :         (void) cntxt;
     169             :         (void) mb;
     170           3 :         if (!(b = BATdescriptor(*bid))) {
     171           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     172           0 :                 goto bailout;
     173             :         }
     174           3 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     175           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     176           0 :                 goto bailout;
     177             :         }
     178           3 :         q = canditer_init(&ci1, b, bs);
     179           3 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
     180           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     181           0 :                 goto bailout;
     182             :         }
     183             : 
     184           3 :         off1 = b->hseqbase;
     185           3 :         bi = bat_iterator(b);
     186           3 :         vals = Tloc(bn, 0);
     187           3 :         if (ci1.tpe == cand_dense) {
     188          10 :                 for (BUN i = 0; i < q; i++) {
     189           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     190           8 :                         x = (str) BUNtvar(bi, p1);
     191             : 
     192           8 :                         if ((msg = str_wchr_at(&next, x, 0)) != MAL_SUCCEED)
     193           0 :                                 goto bailout1;
     194           8 :                         vals[i] = next;
     195           8 :                         nils |= is_int_nil(next);
     196             :                 }
     197             :         } else {
     198          15 :                 for (BUN i = 0; i < q; i++) {
     199          14 :                         oid p1 = (canditer_next(&ci1) - off1);
     200          14 :                         x = (str) BUNtvar(bi, p1);
     201             : 
     202          14 :                         if ((msg = str_wchr_at(&next, x, 0)) != MAL_SUCCEED)
     203           0 :                                 goto bailout1;
     204          14 :                         vals[i] = next;
     205          14 :                         nils |= is_int_nil(next);
     206             :                 }
     207             :         }
     208           1 : bailout1:
     209           3 :         bat_iterator_end(&bi);
     210           3 : bailout:
     211           3 :         finalize_ouput(res, bn, msg, nils, q);
     212           3 :         unfix_inputs(2, b, bs);
     213           3 :         return msg;
     214             : }
     215             : 
     216             : static str
     217           1 : STRbatFromWChr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     218             : {
     219             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     220             :         BUN q = 0;
     221           1 :         size_t buflen = MAX(strlen(str_nil) + 1, 8);
     222             :         int *restrict vals, x;
     223           1 :         str buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     224             :         bool nils = false;
     225           1 :         struct canditer ci1 = {0};
     226             :         oid off1;
     227           1 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     228           1 :                 *sid1 = pci->argc == 3 ? getArgReference_bat(stk, pci, 2) : NULL;
     229             :         BATiter bi;
     230             : 
     231             :         (void) cntxt;
     232             :         (void) mb;
     233           1 :         if (!buf) {
     234           0 :                 msg = createException(MAL, "batstr.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     235           0 :                 goto bailout;
     236             :         }
     237           1 :         if (!(b = BATdescriptor(*bid))) {
     238           0 :                 msg = createException(MAL, "batstr.unicode", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     239           0 :                 goto bailout;
     240             :         }
     241           1 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     242           0 :                 msg = createException(MAL, "batstr.unicode", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     243           0 :                 goto bailout;
     244             :         }
     245           1 :         q = canditer_init(&ci1, b, bs);
     246           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     247           0 :                 msg = createException(MAL, "batstr.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     248           0 :                 goto bailout;
     249             :         }
     250             : 
     251           1 :         bi = bat_iterator(b);
     252           1 :         off1 = b->hseqbase;
     253           1 :         vals = bi.base;
     254           1 :         if (ci1.tpe == cand_dense) {
     255           5 :                 for (BUN i = 0; i < q; i++) {
     256           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     257           4 :                         x = vals[p1];
     258             : 
     259           4 :                         if (is_int_nil(x)) {
     260           2 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     261           0 :                                         bat_iterator_end(&bi);
     262           0 :                                         msg = createException(MAL, "batstr.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     263           0 :                                         goto bailout;
     264             :                                 }
     265             :                                 nils = true;
     266             :                         } else {
     267           2 :                                 if ((msg = str_from_wchr(&buf, &buflen, vals[p1])) != MAL_SUCCEED) {
     268           0 :                                         bat_iterator_end(&bi);
     269           0 :                                         goto bailout;
     270             :                                 }
     271           2 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     272           0 :                                         bat_iterator_end(&bi);
     273           0 :                                         msg = createException(MAL, "batstr.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     274           0 :                                         goto bailout;
     275             :                                 }
     276             :                         }
     277             :                 }
     278             :         } else {
     279           0 :                 for (BUN i = 0; i < q; i++) {
     280           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     281           0 :                         x = vals[p1];
     282             : 
     283           0 :                         if (is_int_nil(x)) {
     284           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     285           0 :                                         bat_iterator_end(&bi);
     286           0 :                                         msg = createException(MAL, "batstr.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     287           0 :                                         goto bailout;
     288             :                                 }
     289             :                                 nils = true;
     290             :                         } else {
     291           0 :                                 if ((msg = str_from_wchr(&buf, &buflen, vals[p1])) != MAL_SUCCEED) {
     292           0 :                                         bat_iterator_end(&bi);
     293           0 :                                         goto bailout;
     294             :                                 }
     295           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     296           0 :                                         bat_iterator_end(&bi);
     297           0 :                                         msg = createException(MAL, "batstr.unicode", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     298           0 :                                         goto bailout;
     299             :                                 }
     300             :                         }
     301             :                 }
     302             :         }
     303           1 :         bat_iterator_end(&bi);
     304           1 : bailout:
     305           1 :         GDKfree(buf);
     306           1 :         finalize_ouput(res, bn, msg, nils, q);
     307           1 :         unfix_inputs(2, b, bs);
     308           1 :         return msg;
     309             : }
     310             : 
     311             : static str
     312           0 : STRbatSpace(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     313             : {
     314             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     315             :         BUN q = 0;
     316           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
     317             :         int *restrict vals, x;
     318           0 :         str buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     319             :         bool nils = false;
     320           0 :         char space[]= " ", *s = space;
     321           0 :         struct canditer ci1 = {0};
     322             :         oid off1;
     323           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     324           0 :                 *sid1 = pci->argc == 3 ? getArgReference_bat(stk, pci, 2) : NULL;
     325             :         BATiter bi;
     326             : 
     327             :         (void) cntxt;
     328             :         (void) mb;
     329           0 :         if (!buf) {
     330           0 :                 msg = createException(MAL, "batstr.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     331           0 :                 goto bailout;
     332             :         }
     333           0 :         if (!(b = BATdescriptor(*bid))) {
     334           0 :                 msg = createException(MAL, "batstr.space", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     335           0 :                 goto bailout;
     336             :         }
     337           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     338           0 :                 msg = createException(MAL, "batstr.search", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     339           0 :                 goto bailout;
     340             :         }
     341           0 :         q = canditer_init(&ci1, b, bs);
     342           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     343           0 :                 msg = createException(MAL, "batstr.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     344           0 :                 goto bailout;
     345             :         }
     346             : 
     347           0 :         off1 = b->hseqbase;
     348           0 :         bi = bat_iterator(b);
     349           0 :         vals = bi.base;
     350           0 :         if (ci1.tpe == cand_dense) {
     351           0 :                 for (BUN i = 0; i < q; i++) {
     352           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     353           0 :                         x = vals[p1];
     354             : 
     355           0 :                         if (is_int_nil(x) || x < 0) {
     356           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     357           0 :                                         msg = createException(MAL, "batstr.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     358           0 :                                         goto bailout;
     359             :                                 }
     360             :                                 nils = true;
     361             :                         } else {
     362           0 :                                 if ((msg = str_repeat(&buf, &buflen, s, x)) != MAL_SUCCEED)
     363           0 :                                         goto bailout;
     364           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     365           0 :                                         msg = createException(MAL, "batstr.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     366           0 :                                         goto bailout;
     367             :                                 }
     368             :                         }
     369             :                 }
     370             :         } else {
     371           0 :                 for (BUN i = 0; i < q; i++) {
     372           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     373           0 :                         x = vals[p1];
     374             : 
     375           0 :                         if (is_int_nil(x) || x < 0) {
     376           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     377           0 :                                         msg = createException(MAL, "batstr.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     378           0 :                                         goto bailout;
     379             :                                 }
     380             :                                 nils = true;
     381             :                         } else {
     382           0 :                                 if ((msg = str_repeat(&buf, &buflen, s, x)) != MAL_SUCCEED)
     383           0 :                                         goto bailout;
     384           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     385           0 :                                         msg = createException(MAL, "batstr.space", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     386           0 :                                         goto bailout;
     387             :                                 }
     388             :                         }
     389             :                 }
     390             :         }
     391           0 :         bat_iterator_end(&bi);
     392           0 : bailout:
     393           0 :         GDKfree(buf);
     394           0 :         finalize_ouput(res, bn, msg, nils, q);
     395           0 :         unfix_inputs(2, b, bs);
     396           0 :         return msg;
     397             : }
     398             : 
     399             : static str
     400         170 : do_batstr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str *, size_t *, str))
     401             : {
     402             :         BATiter bi;
     403             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     404             :         BUN q = 0;
     405         170 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
     406         170 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     407             :         bool nils = false;
     408         170 :         struct canditer ci1 = {0};
     409             :         oid off1;
     410         170 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     411         170 :                 *sid1 = pci->argc == 3 ? getArgReference_bat(stk, pci, 2) : NULL;
     412             : 
     413             :         (void) cntxt;
     414             :         (void) mb;
     415         170 :         if (!buf) {
     416           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     417           0 :                 goto bailout;
     418             :         }
     419         170 :         if (!(b = BATdescriptor(*bid))) {
     420           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     421           0 :                 goto bailout;
     422             :         }
     423         170 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     424           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     425           0 :                 goto bailout;
     426             :         }
     427         170 :         q = canditer_init(&ci1, b, bs);
     428         170 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     429           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     430           0 :                 goto bailout;
     431             :         }
     432             : 
     433         170 :         off1 = b->hseqbase;
     434         170 :         bi = bat_iterator(b);
     435         170 :         if (ci1.tpe == cand_dense) {
     436      263822 :                 for (BUN i = 0; i < q; i++) {
     437      263652 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     438      263652 :                         x = (str) BUNtvar(bi, p1);
     439             : 
     440      263652 :                         if (strNil(x)) {
     441        3071 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     442           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     443           0 :                                         goto bailout1;
     444             :                                 }
     445             :                                 nils = true;
     446             :                         } else {
     447      260581 :                                 if ((msg = (*func)(&buf, &buflen, x)) != MAL_SUCCEED)
     448           0 :                                         goto bailout1;
     449      260579 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     450           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     451           0 :                                         goto bailout1;
     452             :                                 }
     453             :                         }
     454             :                 }
     455             :         } else {
     456           0 :                 for (BUN i = 0; i < q; i++) {
     457           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     458           0 :                         x = (str) BUNtvar(bi, p1);
     459             : 
     460           0 :                         if (strNil(x)) {
     461           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     462           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     463           0 :                                         goto bailout1;
     464             :                                 }
     465             :                                 nils = true;
     466             :                         } else {
     467           0 :                                 if ((msg = (*func)(&buf, &buflen, x)) != MAL_SUCCEED)
     468           0 :                                         goto bailout1;
     469           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     470           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     471           0 :                                         goto bailout1;
     472             :                                 }
     473             :                         }
     474             :                 }
     475             :         }
     476           0 : bailout1:
     477         170 :         bat_iterator_end(&bi);
     478         170 : bailout:
     479         170 :         GDKfree(buf);
     480         170 :         finalize_ouput(res, bn, msg, nils, q);
     481         170 :         unfix_inputs(2, b, bs);
     482         170 :         return msg;
     483             : }
     484             : 
     485             : /* Input: a BAT of strings 'b' and a constant string 'y'
     486             :  * Output type: str (a BAT of strings)
     487             :  */
     488             : static str
     489           7 : do_batstr_conststr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, size_t buflen, str (*func)(str*, size_t*, str, str))
     490             : {
     491             :         BATiter bi;
     492             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     493             :         BUN q = 0;
     494           7 :         str x, y = *getArgReference_str(stk, pci, 2), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     495             :         bool nils = false;
     496           7 :         struct canditer ci1 = {0};
     497             :         oid off1;
     498           7 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     499           7 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     500             : 
     501             :         (void) cntxt;
     502             :         (void) mb;
     503           7 :         if (!buf) {
     504           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     505           0 :                 goto bailout;
     506             :         }
     507           7 :         if (!(b = BATdescriptor(*bid))) {
     508           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     509           0 :                 goto bailout;
     510             :         }
     511           7 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     512           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     513           0 :                 goto bailout;
     514             :         }
     515           7 :         q = canditer_init(&ci1, b, bs);
     516           7 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     517           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     518           0 :                 goto bailout;
     519             :         }
     520             : 
     521           7 :         off1 = b->hseqbase;
     522           7 :         bi = bat_iterator(b);
     523           7 :         if (ci1.tpe == cand_dense) {
     524          25 :                 for (BUN i = 0; i < q; i++) {
     525          18 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     526          18 :                         x = (str) BUNtvar(bi, p1);
     527             : 
     528          36 :                         if (strNil(x) || strNil(y)) {
     529           9 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     530           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     531           0 :                                         goto bailout1;
     532             :                                 }
     533             :                                 nils = true;
     534             :                         } else {
     535           9 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     536           0 :                                         goto bailout1;
     537           9 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     538           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     539           0 :                                         goto bailout1;
     540             :                                 }
     541             :                         }
     542             :                 }
     543             :         } else {
     544           0 :                 for (BUN i = 0; i < q; i++) {
     545           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     546           0 :                         x = (str) BUNtvar(bi, p1);
     547             : 
     548           0 :                         if (strNil(x) || strNil(y)) {
     549           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     550           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     551           0 :                                         goto bailout1;
     552             :                                 }
     553             :                                 nils = true;
     554             :                         } else {
     555           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     556           0 :                                         goto bailout1;
     557           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     558           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     559           0 :                                         goto bailout1;
     560             :                                 }
     561             :                         }
     562             :                 }
     563             :         }
     564           0 : bailout1:
     565           7 :         bat_iterator_end(&bi);
     566           7 : bailout:
     567           7 :         GDKfree(buf);
     568           7 :         finalize_ouput(res, bn, msg, nils, q);
     569           7 :         unfix_inputs(2, b, bs);
     570           7 :         return msg;
     571             : }
     572             : 
     573             : /* Input: a const string 'x' and a BAT of strings 'y'
     574             :  * Output type: str (a BAT of strings)
     575             :  */
     576             : static str
     577           0 : do_batstr_str_conststr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, size_t buflen, str (*func)(str*, size_t*, str, str))
     578             : {
     579             :         BATiter bi;
     580             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     581             :         BUN q = 0;
     582           0 :         str x = *getArgReference_str(stk, pci, 1), y, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     583             :         bool nils = false;
     584           0 :         struct canditer ci1 = {0};
     585             :         oid off1;
     586           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
     587           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     588             : 
     589             :         (void) cntxt;
     590             :         (void) mb;
     591           0 :         if (!buf) {
     592           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     593           0 :                 goto bailout;
     594             :         }
     595           0 :         if (!(b = BATdescriptor(*bid))) {
     596           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     597           0 :                 goto bailout;
     598             :         }
     599           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     600           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     601           0 :                 goto bailout;
     602             :         }
     603           0 :         q = canditer_init(&ci1, b, bs);
     604           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     605           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     606           0 :                 goto bailout;
     607             :         }
     608             : 
     609           0 :         off1 = b->hseqbase;
     610           0 :         bi = bat_iterator(b);
     611           0 :         if (ci1.tpe == cand_dense) {
     612           0 :                 for (BUN i = 0; i < q; i++) {
     613           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     614           0 :                         y = (str) BUNtvar(bi, p1);
     615             : 
     616           0 :                         if (strNil(x) || strNil(y)) {
     617           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     618           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     619           0 :                                         goto bailout1;
     620             :                                 }
     621             :                                 nils = true;
     622             :                         } else {
     623           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     624           0 :                                         goto bailout1;
     625           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     626           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     627           0 :                                         goto bailout1;
     628             :                                 }
     629             :                         }
     630             :                 }
     631             :         } else {
     632           0 :                 for (BUN i = 0; i < q; i++) {
     633           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     634           0 :                         y = (str) BUNtvar(bi, p1);
     635             : 
     636           0 :                         if (strNil(x) || strNil(y)) {
     637           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     638           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     639           0 :                                         goto bailout1;
     640             :                                 }
     641             :                                 nils = true;
     642             :                         } else {
     643           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     644           0 :                                         goto bailout1;
     645           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     646           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     647           0 :                                         goto bailout1;
     648             :                                 }
     649             :                         }
     650             :                 }
     651             :         }
     652           0 : bailout1:
     653           0 :         bat_iterator_end(&bi);
     654           0 : bailout:
     655           0 :         GDKfree(buf);
     656           0 :         finalize_ouput(res, bn, msg, nils, q);
     657           0 :         unfix_inputs(2, b, bs);
     658           0 :         return msg;
     659             : }
     660             : 
     661             : /* Input: two BATs of strings 'l' and 'l2'
     662             :  * Output type: str (a BAT of strings)
     663             :  */
     664             : static str
     665           3 : do_batstr_batstr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, size_t buflen, str (*func)(str*, size_t*, str, str))
     666             : {
     667             :         BATiter lefti, righti;
     668             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
     669             :         BUN q = 0;
     670           3 :         str x, y, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     671             :         bool nils = false;
     672           3 :         struct canditer ci1 = {0}, ci2 = {0};
     673             :         oid off1, off2;
     674           3 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
     675           3 :                 *l2 = getArgReference_bat(stk, pci, 2),
     676           3 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
     677           3 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
     678             : 
     679             :         (void) cntxt;
     680             :         (void) mb;
     681           3 :         if (!buf) {
     682           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     683           0 :                 goto bailout;
     684             :         }
     685           3 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*l2))) {
     686           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     687           0 :                 goto bailout;
     688             :         }
     689           3 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
     690           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     691           0 :                 goto bailout;
     692             :         }
     693           3 :         q = canditer_init(&ci1, left, lefts);
     694           3 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
     695           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
     696           0 :                 goto bailout;
     697             :         }
     698           3 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     699           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     700           0 :                 goto bailout;
     701             :         }
     702             : 
     703           3 :         off1 = left->hseqbase;
     704           3 :         off2 = right->hseqbase;
     705           3 :         lefti = bat_iterator(left);
     706           3 :         righti = bat_iterator(right);
     707           3 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
     708          12 :                 for (BUN i = 0; i < q; i++) {
     709           9 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
     710           9 :                         x = (str) BUNtvar(lefti, p1);
     711           9 :                         y = (str) BUNtvar(righti, p2);
     712             : 
     713          18 :                         if (strNil(x) || strNil(y)) {
     714           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     715           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     716           0 :                                         goto bailout1;
     717             :                                 }
     718             :                                 nils = true;
     719             :                         } else {
     720           9 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     721           0 :                                         goto bailout1;
     722           9 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     723           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     724           0 :                                         goto bailout1;
     725             :                                 }
     726             :                         }
     727             :                 }
     728             :         } else {
     729           0 :                 for (BUN i = 0; i < q; i++) {
     730           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
     731           0 :                         x = (str) BUNtvar(lefti, p1);
     732           0 :                         y = (str) BUNtvar(righti, p2);
     733             : 
     734           0 :                         if (strNil(x) || strNil(y)) {
     735           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     736           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     737           0 :                                         goto bailout1;
     738             :                                 }
     739             :                                 nils = true;
     740             :                         } else {
     741           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     742           0 :                                         goto bailout1;
     743           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     744           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     745           0 :                                         goto bailout1;
     746             :                                 }
     747             :                         }
     748             :                 }
     749             :         }
     750           0 : bailout1:
     751           3 :         bat_iterator_end(&lefti);
     752           3 :         bat_iterator_end(&righti);
     753           3 : bailout:
     754           3 :         GDKfree(buf);
     755           3 :         finalize_ouput(res, bn, msg, nils, q);
     756           3 :         unfix_inputs(4, left, lefts, right, rights);
     757           3 :         return msg;
     758             : }
     759             : 
     760             : /* Input: a BAT of strings 'l' and a constant int 'y'
     761             :  * Output type: str (a BAT of strings)
     762             :  */
     763             : static str
     764           2 : do_batstr_constint_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int))
     765             : {
     766             :         BATiter bi;
     767             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     768             :         BUN q = 0;
     769           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
     770           2 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     771           2 :         int y = *getArgReference_int(stk, pci, 2);
     772             :         bool nils = false;
     773           2 :         struct canditer ci1 = {0};
     774             :         oid off1;
     775           2 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     776           2 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     777             : 
     778             :         (void) cntxt;
     779             :         (void) mb;
     780           2 :         if (!buf) {
     781           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     782           0 :                 goto bailout;
     783             :         }
     784           2 :         if (!(b = BATdescriptor(*bid))) {
     785           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     786           0 :                 goto bailout;
     787             :         }
     788           2 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     789           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     790           0 :                 goto bailout;
     791             :         }
     792           2 :         q = canditer_init(&ci1, b, bs);
     793           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     794           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     795           0 :                 goto bailout;
     796             :         }
     797             : 
     798           2 :         off1 = b->hseqbase;
     799           2 :         bi = bat_iterator(b);
     800           2 :         if (ci1.tpe == cand_dense) {
     801           6 :                 for (BUN i = 0; i < q; i++) {
     802           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     803           4 :                         x = (str) BUNtvar(bi, p1);
     804             : 
     805           4 :                         if (strNil(x) || is_int_nil(y)) {
     806           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     807           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     808           0 :                                         goto bailout1;
     809             :                                 }
     810             :                                 nils = true;
     811             :                         } else {
     812           4 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     813           0 :                                         goto bailout1;
     814           4 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     815           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     816           0 :                                         goto bailout1;
     817             :                                 }
     818             :                         }
     819             :                 }
     820             :         } else {
     821           0 :                 for (BUN i = 0; i < q; i++) {
     822           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     823           0 :                         x = (str) BUNtvar(bi, p1);
     824             : 
     825           0 :                         if (strNil(x) || is_int_nil(y)) {
     826           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     827           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     828           0 :                                         goto bailout1;
     829             :                                 }
     830             :                                 nils = true;
     831             :                         } else {
     832           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     833           0 :                                         goto bailout1;
     834           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     835           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     836           0 :                                         goto bailout1;
     837             :                                 }
     838             :                         }
     839             :                 }
     840             :         }
     841           0 : bailout1:
     842           2 :         bat_iterator_end(&bi);
     843           2 : bailout:
     844           2 :         GDKfree(buf);
     845           2 :         finalize_ouput(res, bn, msg, nils, q);
     846           2 :         unfix_inputs(2, b, bs);
     847           2 :         return msg;
     848             : }
     849             : 
     850             : /* Input: a constant string 'x' and a BAT of integers 'y'
     851             :  * Output type: str (a BAT of strings)
     852             :  */
     853             : static str
     854           0 : do_batstr_int_conststr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int))
     855             : {
     856             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     857             :         BUN q = 0;
     858           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
     859           0 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     860             :         int y, *restrict inputs;
     861             :         bool nils = false;
     862           0 :         struct canditer ci1 = {0};
     863             :         oid off1;
     864           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
     865           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     866             :         BATiter bi;
     867             : 
     868             :         (void) cntxt;
     869             :         (void) mb;
     870           0 :         if (!buf) {
     871           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     872           0 :                 goto bailout;
     873             :         }
     874           0 :         if (!(b = BATdescriptor(*bid))) {
     875           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     876           0 :                 goto bailout;
     877             :         }
     878           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     879           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     880           0 :                 goto bailout;
     881             :         }
     882           0 :         q = canditer_init(&ci1, b, bs);
     883           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     884           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     885           0 :                 goto bailout;
     886             :         }
     887             : 
     888           0 :         off1 = b->hseqbase;
     889           0 :         bi = bat_iterator(b);
     890           0 :         inputs = bi.base;
     891           0 :         if (ci1.tpe == cand_dense) {
     892           0 :                 for (BUN i = 0; i < q; i++) {
     893           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     894           0 :                         y = inputs[p1];
     895             : 
     896           0 :                         if (strNil(x) || is_int_nil(y)) {
     897           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     898           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     899           0 :                                         goto bailout;
     900             :                                 }
     901             :                                 nils = true;
     902             :                         } else {
     903           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     904           0 :                                         goto bailout;
     905           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     906           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     907           0 :                                         goto bailout;
     908             :                                 }
     909             :                         }
     910             :                 }
     911             :         } else {
     912           0 :                 for (BUN i = 0; i < q; i++) {
     913           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     914           0 :                         y = inputs[p1];
     915             : 
     916           0 :                         if (strNil(x) || is_int_nil(y)) {
     917           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     918           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     919           0 :                                         goto bailout;
     920             :                                 }
     921             :                                 nils = true;
     922             :                         } else {
     923           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
     924           0 :                                         goto bailout;
     925           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
     926           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     927           0 :                                         goto bailout;
     928             :                                 }
     929             :                         }
     930             :                 }
     931             :         }
     932           0 :         bat_iterator_end(&bi);
     933           0 : bailout:
     934           0 :         GDKfree(buf);
     935           0 :         finalize_ouput(res, bn, msg, nils, q);
     936           0 :         unfix_inputs(2, b, bs);
     937           0 :         return msg;
     938             : }
     939             : 
     940             : /* Input: a BAT of strings 'l' and a BAT of integers 'n'
     941             :  * Output type: str (a BAT of strings)
     942             :  */
     943             : static str
     944           2 : do_batstr_batint_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int))
     945             : {
     946             :         BATiter lefti;
     947             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *right = NULL, *rs = NULL;
     948             :         BUN q = 0;
     949           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
     950           2 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
     951             :         bool nils = false;
     952             :         int *restrict righti, y;
     953           2 :         struct canditer ci1 = {0}, ci2 = {0};
     954             :         oid off1, off2;
     955           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
     956           2 :                 *n = getArgReference_bat(stk, pci, 2),
     957           2 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
     958           2 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
     959             :         BATiter bi;
     960             : 
     961             :         (void) cntxt;
     962             :         (void) mb;
     963           2 :         if (!buf) {
     964           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     965           0 :                 goto bailout;
     966             :         }
     967           2 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*n))) {
     968           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     969           0 :                 goto bailout;
     970             :         }
     971           2 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) ||
     972           2 :                 (sid2 && !is_bat_nil(*sid2) && !(rs = BATdescriptor(*sid2)))) {
     973           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     974           0 :                 goto bailout;
     975             :         }
     976           2 :         q = canditer_init(&ci1, left, ls);
     977           2 :         if (canditer_init(&ci2, right, rs) != q || ci1.hseq != ci2.hseq) {
     978           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
     979           0 :                 goto bailout;
     980             :         }
     981           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
     982           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     983           0 :                 goto bailout;
     984             :         }
     985             : 
     986           2 :         off1 = left->hseqbase;
     987           2 :         off2 = right->hseqbase;
     988           2 :         lefti = bat_iterator(left);
     989           2 :         bi = bat_iterator(right);
     990           2 :         righti = bi.base;
     991           2 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
     992           6 :                 for (BUN i = 0; i < q; i++) {
     993           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
     994           4 :                         x = (str) BUNtvar(lefti, p1);
     995           4 :                         y = righti[p2];
     996             : 
     997           4 :                         if (strNil(x) || is_int_nil(y)) {
     998           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     999           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1000           0 :                                         goto bailout1;
    1001             :                                 }
    1002             :                                 nils = true;
    1003             :                         } else {
    1004           4 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    1005           0 :                                         goto bailout1;
    1006           4 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1007           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1008           0 :                                         goto bailout1;
    1009             :                                 }
    1010             :                         }
    1011             :                 }
    1012             :         } else {
    1013           0 :                 for (BUN i = 0; i < q; i++) {
    1014           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    1015           0 :                         x = (str) BUNtvar(lefti, p1);
    1016           0 :                         y = righti[p2];
    1017             : 
    1018           0 :                         if (strNil(x) || is_int_nil(y)) {
    1019           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1020           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1021           0 :                                         goto bailout1;
    1022             :                                 }
    1023             :                                 nils = true;
    1024             :                         } else {
    1025           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    1026           0 :                                         goto bailout1;
    1027           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1028           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1029           0 :                                         goto bailout1;
    1030             :                                 }
    1031             :                         }
    1032             :                 }
    1033             :         }
    1034           2 :         bat_iterator_end(&bi);
    1035           2 : bailout1:
    1036           2 :         bat_iterator_end(&lefti);
    1037           2 : bailout:
    1038           2 :         GDKfree(buf);
    1039           2 :         finalize_ouput(res, bn, msg, nils, q);
    1040           2 :         unfix_inputs(4, left, ls, right, rs);
    1041           2 :         return msg;
    1042             : }
    1043             : 
    1044             : /* Input: a BAT of strings 'l', a constant int 'y' and a constant str 'z'
    1045             :  * Output type: str (a BAT of strings)
    1046             :  */
    1047             : static str
    1048           2 : do_batstr_constint_conststr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int, str))
    1049             : {
    1050             :         BATiter bi;
    1051             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    1052             :         BUN q = 0;
    1053           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    1054           2 :         str x, z = *getArgReference_str(stk, pci, 3), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    1055           2 :         int y = *getArgReference_int(stk, pci, 2);
    1056             :         bool nils = false;
    1057           2 :         struct canditer ci1 = {0};
    1058             :         oid off1;
    1059           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    1060           2 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    1061             : 
    1062             :         (void) cntxt;
    1063             :         (void) mb;
    1064           2 :         if (!buf) {
    1065           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1066           0 :                 goto bailout;
    1067             :         }
    1068           2 :         if (!(b = BATdescriptor(*l))) {
    1069           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1070           0 :                 goto bailout;
    1071             :         }
    1072           2 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    1073           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1074           0 :                 goto bailout;
    1075             :         }
    1076           2 :         q = canditer_init(&ci1, b, bs);
    1077           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    1078           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1079           0 :                 goto bailout;
    1080             :         }
    1081             : 
    1082           2 :         off1 = b->hseqbase;
    1083           2 :         bi = bat_iterator(b);
    1084           2 :         if (ci1.tpe == cand_dense) {
    1085          10 :                 for (BUN i = 0; i < q; i++) {
    1086           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    1087           8 :                         x = (str) BUNtvar(bi, p1);
    1088             : 
    1089          16 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1090           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1091           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1092           0 :                                         goto bailout1;
    1093             :                                 }
    1094             :                                 nils = true;
    1095             :                         } else {
    1096           8 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1097           0 :                                         goto bailout1;
    1098           8 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1099           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1100           0 :                                         goto bailout1;
    1101             :                                 }
    1102             :                         }
    1103             :                 }
    1104             :         } else {
    1105           0 :                 for (BUN i = 0; i < q; i++) {
    1106           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    1107           0 :                         x = (str) BUNtvar(bi, p1);
    1108             : 
    1109           0 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1110           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1111           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1112           0 :                                         goto bailout1;
    1113             :                                 }
    1114             :                                 nils = true;
    1115             :                         } else {
    1116           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1117           0 :                                         goto bailout1;
    1118           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1119           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1120           0 :                                         goto bailout1;
    1121             :                                 }
    1122             :                         }
    1123             :                 }
    1124             :         }
    1125           0 : bailout1:
    1126           2 :         bat_iterator_end(&bi);
    1127           2 : bailout:
    1128           2 :         GDKfree(buf);
    1129           2 :         finalize_ouput(res, bn, msg, nils, q);
    1130           2 :         unfix_inputs(2, b, bs);
    1131           2 :         return msg;
    1132             : }
    1133             : 
    1134             : /* Input: a BAT of strings 'l', a BAT of integers 'n' and a constant str 'z'
    1135             :  * Output type: str (a BAT of strings)
    1136             :  */
    1137             : static str
    1138           2 : do_batstr_batint_conststr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int, str))
    1139             : {
    1140             :         BATiter lefti;
    1141             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *right = NULL, *rs = NULL;
    1142             :         BUN q = 0;
    1143           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    1144           2 :         str x, z = *getArgReference_str(stk, pci, 3), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    1145             :         bool nils = false;
    1146             :         int *restrict righti, y;
    1147           2 :         struct canditer ci1 = {0}, ci2 = {0};
    1148             :         oid off1, off2;
    1149           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    1150           2 :                 *n = getArgReference_bat(stk, pci, 2),
    1151           2 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    1152           2 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    1153             :         BATiter bi;
    1154             : 
    1155             :         (void) cntxt;
    1156             :         (void) mb;
    1157           2 :         if (!buf) {
    1158           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1159           0 :                 goto bailout;
    1160             :         }
    1161           2 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*n))) {
    1162           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1163           0 :                 goto bailout;
    1164             :         }
    1165           2 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) ||
    1166           0 :                 (sid2 && !is_bat_nil(*sid2) && !(rs = BATdescriptor(*sid2)))) {
    1167           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1168           0 :                 goto bailout;
    1169             :         }
    1170           2 :         q = canditer_init(&ci1, left, ls);
    1171           2 :         if (canditer_init(&ci2, right, rs) != q || ci1.hseq != ci2.hseq) {
    1172           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1173           0 :                 goto bailout;
    1174             :         }
    1175           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    1176           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1177           0 :                 goto bailout;
    1178             :         }
    1179             : 
    1180           2 :         off1 = left->hseqbase;
    1181           2 :         off2 = right->hseqbase;
    1182           2 :         lefti = bat_iterator(left);
    1183           2 :         bi = bat_iterator(right);
    1184           2 :         righti = bi.base;
    1185           2 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1186          10 :                 for (BUN i = 0; i < q; i++) {
    1187           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    1188           8 :                         x = (str) BUNtvar(lefti, p1);
    1189           8 :                         y = righti[p2];
    1190             : 
    1191          16 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1192           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1193           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1194           0 :                                         goto bailout1;
    1195             :                                 }
    1196             :                                 nils = true;
    1197             :                         } else {
    1198           8 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1199           0 :                                         goto bailout1;
    1200           8 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1201           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1202           0 :                                         goto bailout1;
    1203             :                                 }
    1204             :                         }
    1205             :                 }
    1206             :         } else {
    1207           0 :                 for (BUN i = 0; i < q; i++) {
    1208           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    1209           0 :                         x = (str) BUNtvar(lefti, p1);
    1210           0 :                         y = righti[p2];
    1211             : 
    1212           0 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1213           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1214           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1215           0 :                                         goto bailout1;
    1216             :                                 }
    1217             :                                 nils = true;
    1218             :                         } else {
    1219           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1220           0 :                                         goto bailout1;
    1221           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1222           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1223           0 :                                         goto bailout1;
    1224             :                                 }
    1225             :                         }
    1226             :                 }
    1227             :         }
    1228           2 :         bat_iterator_end(&bi);
    1229           2 : bailout1:
    1230           2 :         bat_iterator_end(&lefti);
    1231           2 : bailout:
    1232           2 :         GDKfree(buf);
    1233           2 :         finalize_ouput(res, bn, msg, nils, q);
    1234           2 :         unfix_inputs(4, left, ls, right, rs);
    1235           2 :         return msg;
    1236             : }
    1237             : 
    1238             : /* Input: a BAT of strings 'l', a constant int 'y' and a BAT of strings 'l2'
    1239             :  * Output type: str (a BAT of strings)
    1240             :  */
    1241             : static str
    1242           2 : do_batstr_constint_batstr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int, str))
    1243             : {
    1244             :         BATiter lefti, righti;
    1245             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *right = NULL, *rs = NULL;
    1246             :         BUN q = 0;
    1247           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    1248           2 :         str x, z, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    1249             :         bool nils = false;
    1250           2 :         int y = *getArgReference_int(stk, pci, 2);
    1251           2 :         struct canditer ci1 = {0}, ci2 = {0};
    1252             :         oid off1, off2;
    1253           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    1254           2 :                 *l2 = getArgReference_bat(stk, pci, 3),
    1255           2 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    1256           2 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    1257             : 
    1258             :         (void) cntxt;
    1259             :         (void) mb;
    1260           2 :         if (!buf) {
    1261           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1262           0 :                 goto bailout;
    1263             :         }
    1264           2 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*l2))) {
    1265           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1266           0 :                 goto bailout;
    1267             :         }
    1268           2 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) ||
    1269           0 :                 (sid2 && !is_bat_nil(*sid2) && !(rs = BATdescriptor(*sid2)))) {
    1270           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1271           0 :                 goto bailout;
    1272             :         }
    1273           2 :         q = canditer_init(&ci1, left, ls);
    1274           2 :         if (canditer_init(&ci2, right, rs) != q || ci1.hseq != ci2.hseq) {
    1275           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1276           0 :                 goto bailout;
    1277             :         }
    1278           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    1279           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1280           0 :                 goto bailout;
    1281             :         }
    1282             : 
    1283           2 :         off1 = left->hseqbase;
    1284           2 :         off2 = right->hseqbase;
    1285           2 :         lefti = bat_iterator(left);
    1286           2 :         righti = bat_iterator(right);
    1287           2 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1288          10 :                 for (BUN i = 0; i < q; i++) {
    1289           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    1290           8 :                         x = (str) BUNtvar(lefti, p1);
    1291           8 :                         z = (str) BUNtvar(righti, p2);
    1292             : 
    1293          16 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1294           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1295           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1296           0 :                                         goto bailout1;
    1297             :                                 }
    1298             :                                 nils = true;
    1299             :                         } else {
    1300           8 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1301           0 :                                         goto bailout1;
    1302           8 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1303           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1304           0 :                                         goto bailout1;
    1305             :                                 }
    1306             :                         }
    1307             :                 }
    1308             :         } else {
    1309           0 :                 for (BUN i = 0; i < q; i++) {
    1310           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    1311           0 :                         x = (str) BUNtvar(lefti, p1);
    1312           0 :                         z = (str) BUNtvar(righti, p2);
    1313             : 
    1314           0 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1315           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1316           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1317           0 :                                         goto bailout1;
    1318             :                                 }
    1319             :                                 nils = true;
    1320             :                         } else {
    1321           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1322           0 :                                         goto bailout1;
    1323           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1324           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1325           0 :                                         goto bailout1;
    1326             :                                 }
    1327             :                         }
    1328             :                 }
    1329             :         }
    1330           0 : bailout1:
    1331           2 :         bat_iterator_end(&lefti);
    1332           2 :         bat_iterator_end(&righti);
    1333           2 : bailout:
    1334           2 :         GDKfree(buf);
    1335           2 :         finalize_ouput(res, bn, msg, nils, q);
    1336           2 :         unfix_inputs(4, left, ls, right, rs);
    1337           2 :         return msg;
    1338             : }
    1339             : 
    1340             : /* Input: a BAT of strings 'l', a BAT of int 'n' and a BAT of strings 'l2'
    1341             :  * Output type: str (a BAT of strings)
    1342             :  */
    1343             : static str
    1344           2 : do_batstr_batint_batstr_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int, str))
    1345             : {
    1346             :         BATiter arg1i, arg3i, bi;
    1347             :         BAT *bn = NULL, *arg1 = NULL, *arg1s = NULL, *arg2 = NULL, *arg2s = NULL, *arg3 = NULL, *arg3s = NULL;
    1348             :         BUN q = 0;
    1349           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    1350           2 :         str x, z, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    1351             :         bool nils = false;
    1352             :         int *restrict arg2i, y;
    1353           2 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0};
    1354             :         oid off1, off2, off3;
    1355           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    1356           2 :                 *n = getArgReference_bat(stk, pci, 2), *l2 = getArgReference_bat(stk, pci, 3),
    1357           2 :                 *sid1 = pci->argc == 7 ? getArgReference_bat(stk, pci, 4) : NULL,
    1358           2 :                 *sid2 = pci->argc == 7 ? getArgReference_bat(stk, pci, 5) : NULL,
    1359           2 :                 *sid3 = pci->argc == 7 ? getArgReference_bat(stk, pci, 6) : NULL;
    1360             : 
    1361             :         (void) cntxt;
    1362             :         (void) mb;
    1363           2 :         if (!buf) {
    1364           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1365           0 :                 goto bailout;
    1366             :         }
    1367           2 :         if (!(arg1 = BATdescriptor(*l)) || !(arg2 = BATdescriptor(*n)) || !(arg3 = BATdescriptor(*l2))) {
    1368           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1369           0 :                 goto bailout;
    1370             :         }
    1371           2 :         if ((sid1 && !is_bat_nil(*sid1) && !(arg1s = BATdescriptor(*sid1))) ||
    1372           2 :                 (sid2 && !is_bat_nil(*sid2) && !(arg2s = BATdescriptor(*sid2))) || (sid3 && !is_bat_nil(*sid3) && !(arg3s = BATdescriptor(*sid3)))) {
    1373           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1374           0 :                 goto bailout;
    1375             :         }
    1376           2 :         q = canditer_init(&ci1, arg1, arg1s);
    1377           2 :         if (canditer_init(&ci2, arg2, arg2s) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, arg3, arg3s) != q || ci2.hseq != ci3.hseq) {
    1378           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1379           0 :                 goto bailout;
    1380             :         }
    1381           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    1382           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1383           0 :                 goto bailout;
    1384             :         }
    1385             : 
    1386           2 :         off1 = arg1->hseqbase;
    1387           2 :         off2 = arg2->hseqbase;
    1388           2 :         off3 = arg3->hseqbase;
    1389           2 :         arg1i = bat_iterator(arg1);
    1390           2 :         bi = bat_iterator(arg2);
    1391           2 :         arg2i = bi.base;
    1392           2 :         arg3i = bat_iterator(arg3);
    1393           2 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense) {
    1394          10 :                 for (BUN i = 0; i < q; i++) {
    1395           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2), p3 = (canditer_next_dense(&ci3) - off3);
    1396           8 :                         x = (str) BUNtvar(arg1i, p1);
    1397           8 :                         y = arg2i[p2];
    1398           8 :                         z = (str) BUNtvar(arg3i, p3);
    1399             : 
    1400          16 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1401           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1402           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1403           0 :                                         goto bailout1;
    1404             :                                 }
    1405             :                                 nils = true;
    1406             :                         } else {
    1407           8 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1408           0 :                                         goto bailout1;
    1409           8 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1410           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1411           0 :                                         goto bailout1;
    1412             :                                 }
    1413             :                         }
    1414             :                 }
    1415             :         } else {
    1416           0 :                 for (BUN i = 0; i < q; i++) {
    1417           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2), p3 = (canditer_next(&ci3) - off3);
    1418           0 :                         x = (str) BUNtvar(arg1i, p1);
    1419           0 :                         y = arg2i[p2];
    1420           0 :                         z = (str) BUNtvar(arg3i, p3);
    1421             : 
    1422           0 :                         if (strNil(x) || is_int_nil(y) || strNil(z)) {
    1423           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    1424           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1425           0 :                                         goto bailout1;
    1426             :                                 }
    1427             :                                 nils = true;
    1428             :                         } else {
    1429           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    1430           0 :                                         goto bailout1;
    1431           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    1432           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1433           0 :                                         goto bailout1;
    1434             :                                 }
    1435             :                         }
    1436             :                 }
    1437             :         }
    1438           0 : bailout1:
    1439           2 :         bat_iterator_end(&arg1i);
    1440           2 :         bat_iterator_end(&arg3i);
    1441           2 :         bat_iterator_end(&bi);
    1442           2 : bailout:
    1443           2 :         GDKfree(buf);
    1444           2 :         finalize_ouput(res, bn, msg, nils, q);
    1445           2 :         unfix_inputs(6, arg1, arg1s, arg2, arg2s, arg3, arg3s);
    1446           2 :         return msg;
    1447             : }
    1448             : 
    1449             : static str
    1450         116 : STRbatLower(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1451             : {
    1452             :         str msg = MAL_SUCCEED;
    1453             : 
    1454         116 :         if ((msg = str_case_hash_lock(false)))
    1455             :                 return msg;
    1456         116 :         msg = do_batstr_str(cntxt, mb, stk, pci, "batstr.lower", str_lower);
    1457         116 :         str_case_hash_unlock(false);
    1458         116 :         return msg;
    1459             : }
    1460             : 
    1461             : static str
    1462          10 : STRbatUpper(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1463             : {
    1464             :         str msg = MAL_SUCCEED;
    1465             : 
    1466          10 :         if ((msg = str_case_hash_lock(true)))
    1467             :                 return msg;
    1468          10 :         msg = do_batstr_str(cntxt, mb, stk, pci, "batstr.upper", str_upper);
    1469          10 :         str_case_hash_unlock(true);
    1470          10 :         return msg;
    1471             : }
    1472             : 
    1473             : static str
    1474          11 : STRbatStrip(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1475             : {
    1476          11 :         return do_batstr_str(cntxt, mb, stk, pci, "batstr.strip", str_strip);
    1477             : }
    1478             : 
    1479             : static str
    1480           2 : STRbatLtrim(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1481             : {
    1482           2 :         return do_batstr_str(cntxt, mb, stk, pci, "batstr.ltrim", str_ltrim);
    1483             : }
    1484             : 
    1485             : static str
    1486          31 : STRbatRtrim(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1487             : {
    1488          31 :         return do_batstr_str(cntxt, mb, stk, pci, "batstr.rtrim", str_rtrim);
    1489             : }
    1490             : 
    1491             : static str
    1492           5 : STRbatStrip2_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1493             : {
    1494           5 :         return do_batstr_conststr_str(cntxt, mb, stk, pci, "batstr.strip", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_strip2);
    1495             : }
    1496             : 
    1497             : static str
    1498           1 : STRbatLtrim2_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1499             : {
    1500           1 :         return do_batstr_conststr_str(cntxt, mb, stk, pci, "batstr.ltrim", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_ltrim2);
    1501             : }
    1502             : 
    1503             : static str
    1504           1 : STRbatRtrim2_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1505             : {
    1506           1 :         return do_batstr_conststr_str(cntxt, mb, stk, pci, "batstr.rtrim", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_rtrim2);
    1507             : }
    1508             : 
    1509             : static str
    1510           0 : STRbatStrip2_1st_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1511             : {
    1512           0 :         return do_batstr_str_conststr(cntxt, mb, stk, pci, "batstr.strip", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_strip2);
    1513             : }
    1514             : 
    1515             : static str
    1516           0 : STRbatLtrim2_1st_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1517             : {
    1518           0 :         return do_batstr_str_conststr(cntxt, mb, stk, pci, "batstr.ltrim", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_ltrim2);
    1519             : }
    1520             : 
    1521             : static str
    1522           0 : STRbatRtrim2_1st_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1523             : {
    1524           0 :         return do_batstr_str_conststr(cntxt, mb, stk, pci, "batstr.rtrim", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_rtrim2);
    1525             : }
    1526             : 
    1527             : static str
    1528           1 : STRbatStrip2_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1529             : {
    1530           1 :         return do_batstr_batstr_str(cntxt, mb, stk, pci, "batstr.strip", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_strip2);
    1531             : }
    1532             : 
    1533             : static str
    1534           1 : STRbatLtrim2_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1535             : {
    1536           1 :         return do_batstr_batstr_str(cntxt, mb, stk, pci, "batstr.ltrim", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_ltrim2);
    1537             : }
    1538             : 
    1539             : static str
    1540           1 : STRbatRtrim2_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1541             : {
    1542           1 :         return do_batstr_batstr_str(cntxt, mb, stk, pci, "batstr.rtrim", INITIAL_STR_BUFFER_LENGTH * sizeof(int), str_rtrim2);
    1543             : }
    1544             : 
    1545             : static str
    1546           1 : STRbatLpad_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1547             : {
    1548           1 :         return do_batstr_constint_str(cntxt, mb, stk, pci, "batstr.lpad", str_lpad);
    1549             : }
    1550             : 
    1551             : static str
    1552           1 : STRbatRpad_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1553             : {
    1554           1 :         return do_batstr_constint_str(cntxt, mb, stk, pci, "batstr.rpad", str_rpad);
    1555             : }
    1556             : 
    1557             : static str
    1558           0 : STRbatLpad_1st_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1559             : {
    1560           0 :         return do_batstr_int_conststr(cntxt, mb, stk, pci, "batstr.lpad", str_lpad);
    1561             : }
    1562             : 
    1563             : static str
    1564           0 : STRbatRpad_1st_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1565             : {
    1566           0 :         return do_batstr_int_conststr(cntxt, mb, stk, pci, "batstr.rpad", str_rpad);
    1567             : }
    1568             : 
    1569             : static str
    1570           1 : STRbatLpad_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1571             : {
    1572           1 :         return do_batstr_batint_str(cntxt, mb, stk, pci, "batstr.lpad", str_lpad);
    1573             : }
    1574             : 
    1575             : static str
    1576           1 : STRbatRpad_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1577             : {
    1578           1 :         return do_batstr_batint_str(cntxt, mb, stk, pci, "batstr.rpad", str_rpad);
    1579             : }
    1580             : 
    1581             : static str
    1582           1 : STRbatLpad3_const_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1583             : {
    1584           1 :         return do_batstr_constint_conststr_str(cntxt, mb, stk, pci, "batstr.lpad", str_lpad3);
    1585             : }
    1586             : 
    1587             : static str
    1588           1 : STRbatRpad3_const_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1589             : {
    1590           1 :         return do_batstr_constint_conststr_str(cntxt, mb, stk, pci, "batstr.rpad", str_rpad3);
    1591             : }
    1592             : 
    1593             : static str
    1594           1 : STRbatLpad3_bat_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1595             : {
    1596           1 :         return do_batstr_batint_conststr_str(cntxt, mb, stk, pci, "batstr.lpad", str_lpad3);
    1597             : }
    1598             : 
    1599             : static str
    1600           1 : STRbatRpad3_bat_const(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1601             : {
    1602           1 :         return do_batstr_batint_conststr_str(cntxt, mb, stk, pci, "batstr.rpad", str_rpad3);
    1603             : }
    1604             : 
    1605             : static str
    1606           1 : STRbatLpad3_const_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1607             : {
    1608           1 :         return do_batstr_constint_batstr_str(cntxt, mb, stk, pci, "batstr.lpad", str_lpad3);
    1609             : }
    1610             : 
    1611             : static str
    1612           1 : STRbatRpad3_const_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1613             : {
    1614           1 :         return do_batstr_constint_batstr_str(cntxt, mb, stk, pci, "batstr.rpad", str_rpad3);
    1615             : }
    1616             : 
    1617             : static str
    1618           1 : STRbatLpad3_bat_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1619             : {
    1620           1 :         return do_batstr_batint_batstr_str(cntxt, mb, stk, pci, "batstr.lpad", str_lpad3);
    1621             : }
    1622             : 
    1623             : static str
    1624           1 : STRbatRpad3_bat_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1625             : {
    1626           1 :         return do_batstr_batint_batstr_str(cntxt, mb, stk, pci, "batstr.rpad", str_rpad3);
    1627             : }
    1628             : 
    1629             : /*
    1630             :  * A general assumption in all cases is the bats are synchronized on their
    1631             :  * head column. This is not checked and may be mis-used to deploy the
    1632             :  * implementation for shifted window arithmetic as well.
    1633             :  */
    1634             : 
    1635             : static str
    1636           0 : prefix_or_suffix(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, bit (*func)(str, str))
    1637             : {
    1638             :         BATiter lefti, righti;
    1639             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
    1640             :         BUN q = 0;
    1641             :         bit *restrict vals;
    1642             :         str x, y, msg = MAL_SUCCEED;
    1643             :         bool nils = false;
    1644           0 :         struct canditer ci1 = {0}, ci2 = {0};
    1645             :         oid off1, off2;
    1646           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    1647           0 :                 *r = getArgReference_bat(stk, pci, 2),
    1648           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
    1649           0 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    1650             : 
    1651             :         (void) cntxt;
    1652             :         (void) mb;
    1653           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
    1654           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1655           0 :                 goto bailout;
    1656             :         }
    1657           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
    1658           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1659           0 :                 goto bailout;
    1660             :         }
    1661           0 :         q = canditer_init(&ci1, left, lefts);
    1662           0 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
    1663           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1664           0 :                 goto bailout;
    1665             :         }
    1666           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_bit, q, TRANSIENT))) {
    1667           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1668           0 :                 goto bailout;
    1669             :         }
    1670             : 
    1671           0 :         off1 = left->hseqbase;
    1672           0 :         off2 = right->hseqbase;
    1673           0 :         lefti = bat_iterator(left);
    1674           0 :         righti = bat_iterator(right);
    1675           0 :         vals = Tloc(bn, 0);
    1676           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1677           0 :                 for (BUN i = 0; i < q; i++) {
    1678           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    1679           0 :                         x = (str) BUNtvar(lefti, p1);
    1680           0 :                         y = (str) BUNtvar(righti, p2);
    1681             : 
    1682           0 :                         if (strNil(x) || strNil(y)) {
    1683           0 :                                 vals[i] = int_nil;
    1684           0 :                                 nils = true;
    1685             :                         } else {
    1686           0 :                                 vals[i] = func(x, y);
    1687             :                         }
    1688             :                 }
    1689             :         } else {
    1690           0 :                 for (BUN i = 0; i < q; i++) {
    1691           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    1692           0 :                         x = (str) BUNtvar(lefti, p1);
    1693           0 :                         y = (str) BUNtvar(righti, p2);
    1694             : 
    1695           0 :                         if (strNil(x) || strNil(y)) {
    1696           0 :                                 vals[i] = int_nil;
    1697           0 :                                 nils = true;
    1698             :                         } else {
    1699           0 :                                 vals[i] = func(x, y);
    1700             :                         }
    1701             :                 }
    1702             :         }
    1703           0 :         bat_iterator_end(&lefti);
    1704           0 :         bat_iterator_end(&righti);
    1705           0 : bailout:
    1706           0 :         finalize_ouput(res, bn, msg, nils, q);
    1707           0 :         unfix_inputs(4, left, lefts, right, rights);
    1708           0 :         return msg;
    1709             : }
    1710             : 
    1711             : static str
    1712           0 : STRbatPrefix(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1713             : {
    1714           0 :         return prefix_or_suffix(cntxt, mb, stk, pci, "batstr.startsWith", str_is_prefix);
    1715             : }
    1716             : 
    1717             : static str
    1718           0 : STRbatSuffix(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1719             : {
    1720           0 :         return prefix_or_suffix(cntxt, mb, stk, pci, "batstr.endsWith", str_is_suffix);
    1721             : }
    1722             : 
    1723             : static str
    1724           0 : prefix_or_suffix_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, bit (*func)(str, str))
    1725             : {
    1726             :         BATiter bi;
    1727             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    1728             :         BUN q = 0;
    1729             :         bit *restrict vals;
    1730           0 :         str x, y = *getArgReference_str(stk, pci, 2), msg = MAL_SUCCEED;
    1731             :         bool nils = false;
    1732           0 :         struct canditer ci1 = {0};
    1733             :         oid off1;
    1734           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    1735           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    1736             : 
    1737             :         (void) cntxt;
    1738             :         (void) mb;
    1739           0 :         if (!(b = BATdescriptor(*bid))) {
    1740           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1741           0 :                 goto bailout;
    1742             :         }
    1743           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    1744           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1745           0 :                 goto bailout;
    1746             :         }
    1747           0 :         q = canditer_init(&ci1, b, bs);
    1748           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_bit, q, TRANSIENT))) {
    1749           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1750           0 :                 goto bailout;
    1751             :         }
    1752             : 
    1753           0 :         off1 = b->hseqbase;
    1754           0 :         bi = bat_iterator(b);
    1755           0 :         vals = Tloc(bn, 0);
    1756           0 :         if (ci1.tpe == cand_dense) {
    1757           0 :                 for (BUN i = 0; i < q; i++) {
    1758           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    1759           0 :                         x = (str) BUNtvar(bi, p1);
    1760             : 
    1761           0 :                         if (strNil(x) || strNil(y)) {
    1762           0 :                                 vals[i] = bit_nil;
    1763           0 :                                 nils = true;
    1764             :                         } else {
    1765           0 :                                 vals[i] = func(x, y);
    1766             :                         }
    1767             :                 }
    1768             :         } else {
    1769           0 :                 for (BUN i = 0; i < q; i++) {
    1770           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    1771           0 :                         x = (str) BUNtvar(bi, p1);
    1772             : 
    1773           0 :                         if (strNil(x) || strNil(y)) {
    1774           0 :                                 vals[i] = int_nil;
    1775           0 :                                 nils = true;
    1776             :                         } else {
    1777           0 :                                 vals[i] = func(x, y);
    1778             :                         }
    1779             :                 }
    1780             :         }
    1781           0 :         bat_iterator_end(&bi);
    1782           0 : bailout:
    1783           0 :         finalize_ouput(res, bn, msg, nils, q);
    1784           0 :         unfix_inputs(2, b, bs);
    1785           0 :         return msg;
    1786             : }
    1787             : 
    1788             : static str
    1789           0 : STRbatPrefixcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1790             : {
    1791           0 :         return prefix_or_suffix_cst(cntxt, mb, stk, pci, "batstr.startsWith", str_is_prefix);
    1792             : }
    1793             : 
    1794             : static str
    1795           0 : STRbatSuffixcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1796             : {
    1797           0 :         return prefix_or_suffix_cst(cntxt, mb, stk, pci, "batstr.endsWith", str_is_suffix);
    1798             : }
    1799             : 
    1800             : static str
    1801           0 : prefix_or_suffix_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, bit (*func)(str, str))
    1802             : {
    1803             :         BATiter bi;
    1804             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    1805             :         BUN q = 0;
    1806             :         bit *restrict vals;
    1807           0 :         str x = *getArgReference_str(stk, pci, 1), y, msg = MAL_SUCCEED;
    1808             :         bool nils = false;
    1809           0 :         struct canditer ci1 = {0};
    1810             :         oid off1;
    1811           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
    1812           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    1813             : 
    1814             :         (void) cntxt;
    1815             :         (void) mb;
    1816           0 :         if (!(b = BATdescriptor(*bid))) {
    1817           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1818           0 :                 goto bailout;
    1819             :         }
    1820           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    1821           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1822           0 :                 goto bailout;
    1823             :         }
    1824           0 :         q = canditer_init(&ci1, b, bs);
    1825           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_bit, q, TRANSIENT))) {
    1826           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1827           0 :                 goto bailout;
    1828             :         }
    1829             : 
    1830           0 :         off1 = b->hseqbase;
    1831           0 :         bi = bat_iterator(b);
    1832           0 :         vals = Tloc(bn, 0);
    1833           0 :         if (ci1.tpe == cand_dense) {
    1834           0 :                 for (BUN i = 0; i < q; i++) {
    1835           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    1836           0 :                         y = (str) BUNtvar(bi, p1);
    1837             : 
    1838           0 :                         if (strNil(x) || strNil(y)) {
    1839           0 :                                 vals[i] = bit_nil;
    1840           0 :                                 nils = true;
    1841             :                         } else {
    1842           0 :                                 vals[i] = func(x, y);
    1843             :                         }
    1844             :                 }
    1845             :         } else {
    1846           0 :                 for (BUN i = 0; i < q; i++) {
    1847           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    1848           0 :                         y = (str) BUNtvar(bi, p1);
    1849             : 
    1850           0 :                         if (strNil(x) || strNil(y)) {
    1851           0 :                                 vals[i] = int_nil;
    1852           0 :                                 nils = true;
    1853             :                         } else {
    1854           0 :                                 vals[i] = func(x, y);
    1855             :                         }
    1856             :                 }
    1857             :         }
    1858           0 :         bat_iterator_end(&bi);
    1859           0 : bailout:
    1860           0 :         finalize_ouput(res, bn, msg, nils, q);
    1861           0 :         unfix_inputs(2, b, bs);
    1862           0 :         return msg;
    1863             : }
    1864             : 
    1865             : static str
    1866           0 : STRbatPrefix_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1867             : {
    1868           0 :         return prefix_or_suffix_strcst(cntxt, mb, stk, pci, "batstr.startsWith", str_is_prefix);
    1869             : }
    1870             : 
    1871             : static str
    1872           0 : STRbatSuffix_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1873             : {
    1874           0 :         return prefix_or_suffix_strcst(cntxt, mb, stk, pci, "batstr.endsWith", str_is_suffix);
    1875             : }
    1876             : 
    1877             : static str
    1878           1 : search_string_bat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, int (*func)(str, str))
    1879             : {
    1880             :         BATiter lefti, righti;
    1881             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
    1882             :         BUN q = 0;
    1883             :         int *restrict vals;
    1884             :         str x, y, msg = MAL_SUCCEED;
    1885             :         bool nils = false;
    1886           1 :         struct canditer ci1 = {0}, ci2 = {0};
    1887             :         oid off1, off2;
    1888           1 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    1889           1 :                 *r = getArgReference_bat(stk, pci, 2),
    1890           1 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
    1891           1 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    1892             : 
    1893             :         (void) cntxt;
    1894             :         (void) mb;
    1895           1 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
    1896           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1897           0 :                 goto bailout;
    1898             :         }
    1899           1 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
    1900           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1901           0 :                 goto bailout;
    1902             :         }
    1903           1 :         q = canditer_init(&ci1, left, lefts);
    1904           1 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
    1905           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1906           0 :                 goto bailout;
    1907             :         }
    1908           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    1909           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1910           0 :                 goto bailout;
    1911             :         }
    1912             : 
    1913           1 :         off1 = left->hseqbase;
    1914           1 :         off2 = right->hseqbase;
    1915           1 :         lefti = bat_iterator(left);
    1916           1 :         righti = bat_iterator(right);
    1917           1 :         vals = Tloc(bn, 0);
    1918           1 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1919           5 :                 for (BUN i = 0; i < q; i++) {
    1920           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    1921           4 :                         x = (str) BUNtvar(lefti, p1);
    1922           4 :                         y = (str) BUNtvar(righti, p2);
    1923             : 
    1924           8 :                         if (strNil(x) || strNil(y)) {
    1925           0 :                                 vals[i] = int_nil;
    1926           0 :                                 nils = true;
    1927             :                         } else {
    1928           4 :                                 vals[i] = func(x, y);
    1929             :                         }
    1930             :                 }
    1931             :         } else {
    1932           0 :                 for (BUN i = 0; i < q; i++) {
    1933           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    1934           0 :                         x = (str) BUNtvar(lefti, p1);
    1935           0 :                         y = (str) BUNtvar(righti, p2);
    1936             : 
    1937           0 :                         if (strNil(x) || strNil(y)) {
    1938           0 :                                 vals[i] = int_nil;
    1939           0 :                                 nils = true;
    1940             :                         } else {
    1941           0 :                                 vals[i] = func(x, y);
    1942             :                         }
    1943             :                 }
    1944             :         }
    1945           1 :         bat_iterator_end(&lefti);
    1946           1 :         bat_iterator_end(&righti);
    1947           1 : bailout:
    1948           1 :         finalize_ouput(res, bn, msg, nils, q);
    1949           1 :         unfix_inputs(4, left, lefts, right, rights);
    1950           1 :         return msg;
    1951             : }
    1952             : 
    1953             : static str
    1954           1 : STRbatstrSearch(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1955             : {
    1956           1 :         return search_string_bat(cntxt, mb, stk, pci, "batstr.search", str_search);
    1957             : }
    1958             : 
    1959             : static str
    1960           0 : STRbatRstrSearch(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1961             : {
    1962           0 :         return search_string_bat(cntxt, mb, stk, pci, "batstr.r_search", str_reverse_str_search);
    1963             : }
    1964             : 
    1965             : static str
    1966           1 : search_string_bat_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, int (*func)(str, str))
    1967             : {
    1968             :         BATiter bi;
    1969             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    1970             :         BUN q = 0;
    1971             :         int *restrict vals;
    1972           1 :         str x, y = *getArgReference_str(stk, pci, 2), msg = MAL_SUCCEED;
    1973             :         bool nils = false;
    1974           1 :         struct canditer ci1 = {0};
    1975             :         oid off1;
    1976           1 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    1977           1 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    1978             : 
    1979             :         (void) cntxt;
    1980             :         (void) mb;
    1981           1 :         if (!(b = BATdescriptor(*bid))) {
    1982           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1983           0 :                 goto bailout;
    1984             :         }
    1985           1 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    1986           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1987           0 :                 goto bailout;
    1988             :         }
    1989           1 :         q = canditer_init(&ci1, b, bs);
    1990           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    1991           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1992           0 :                 goto bailout;
    1993             :         }
    1994             : 
    1995           1 :         off1 = b->hseqbase;
    1996           1 :         bi = bat_iterator(b);
    1997           1 :         vals = Tloc(bn, 0);
    1998           1 :         if (ci1.tpe == cand_dense) {
    1999           5 :                 for (BUN i = 0; i < q; i++) {
    2000           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2001           4 :                         x = (str) BUNtvar(bi, p1);
    2002             : 
    2003           8 :                         if (strNil(x) || strNil(y)) {
    2004           0 :                                 vals[i] = int_nil;
    2005           0 :                                 nils = true;
    2006             :                         } else {
    2007           4 :                                 vals[i] = func(x, y);
    2008             :                         }
    2009             :                 }
    2010             :         } else {
    2011           0 :                 for (BUN i = 0; i < q; i++) {
    2012           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2013           0 :                         x = (str) BUNtvar(bi, p1);
    2014             : 
    2015           0 :                         if (strNil(x) || strNil(y)) {
    2016           0 :                                 vals[i] = int_nil;
    2017           0 :                                 nils = true;
    2018             :                         } else {
    2019           0 :                                 vals[i] = func(x, y);
    2020             :                         }
    2021             :                 }
    2022             :         }
    2023           1 :         bat_iterator_end(&bi);
    2024           1 : bailout:
    2025           1 :         finalize_ouput(res, bn, msg, nils, q);
    2026           1 :         unfix_inputs(2, b, bs);
    2027           1 :         return msg;
    2028             : }
    2029             : 
    2030             : static str
    2031           1 : STRbatstrSearchcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2032             : {
    2033           1 :         return search_string_bat_cst(cntxt, mb, stk, pci, "batstr.search", str_search);
    2034             : }
    2035             : 
    2036             : static str
    2037           0 : STRbatRstrSearchcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2038             : {
    2039           0 :         return search_string_bat_cst(cntxt, mb, stk, pci, "batstr.r_search", str_reverse_str_search);
    2040             : }
    2041             : 
    2042             : static str
    2043           0 : search_string_bat_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, int (*func)(str, str))
    2044             : {
    2045             :         BATiter bi;
    2046             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2047             :         BUN q = 0;
    2048             :         int *restrict vals;
    2049           0 :         str x = *getArgReference_str(stk, pci, 1), y, msg = MAL_SUCCEED;
    2050             :         bool nils = false;
    2051           0 :         struct canditer ci1 = {0};
    2052             :         oid off1;
    2053           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
    2054           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2055             : 
    2056             :         (void) cntxt;
    2057             :         (void) mb;
    2058           0 :         if (!(b = BATdescriptor(*bid))) {
    2059           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2060           0 :                 goto bailout;
    2061             :         }
    2062           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2063           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2064           0 :                 goto bailout;
    2065             :         }
    2066           0 :         q = canditer_init(&ci1, b, bs);
    2067           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    2068           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2069           0 :                 goto bailout;
    2070             :         }
    2071             : 
    2072           0 :         off1 = b->hseqbase;
    2073           0 :         bi = bat_iterator(b);
    2074           0 :         vals = Tloc(bn, 0);
    2075           0 :         if (ci1.tpe == cand_dense) {
    2076           0 :                 for (BUN i = 0; i < q; i++) {
    2077           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2078           0 :                         y = (str) BUNtvar(bi, p1);
    2079             : 
    2080           0 :                         if (strNil(x) || strNil(y)) {
    2081           0 :                                 vals[i] = int_nil;
    2082           0 :                                 nils = true;
    2083             :                         } else {
    2084           0 :                                 vals[i] = func(x, y);
    2085             :                         }
    2086             :                 }
    2087             :         } else {
    2088           0 :                 for (BUN i = 0; i < q; i++) {
    2089           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2090           0 :                         y = (str) BUNtvar(bi, p1);
    2091             : 
    2092           0 :                         if (strNil(x) || strNil(y)) {
    2093           0 :                                 vals[i] = int_nil;
    2094           0 :                                 nils = true;
    2095             :                         } else {
    2096           0 :                                 vals[i] = func(x, y);
    2097             :                         }
    2098             :                 }
    2099             :         }
    2100           0 :         bat_iterator_end(&bi);
    2101           0 : bailout:
    2102           0 :         finalize_ouput(res, bn, msg, nils, q);
    2103           0 :         unfix_inputs(2, b, bs);
    2104           0 :         return msg;
    2105             : }
    2106             : 
    2107             : static str
    2108           0 : STRbatstrSearch_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2109             : {
    2110           0 :         return search_string_bat_strcst(cntxt, mb, stk, pci, "batstr.search", str_search);
    2111             : }
    2112             : 
    2113             : static str
    2114           0 : STRbatRstrSearch_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2115             : {
    2116           0 :         return search_string_bat_strcst(cntxt, mb, stk, pci, "batstr.r_search", str_reverse_str_search);
    2117             : }
    2118             : 
    2119             : static str
    2120           0 : STRbatWChrAt(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2121             : {
    2122             :         BATiter lefti, bi;
    2123             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
    2124             :         BUN q = 0;
    2125             :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2126             :         int *restrict righti, *restrict vals, next, y;
    2127           0 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2128             :         bool nils = false;
    2129           0 :         struct canditer ci1 = {0}, ci2 = {0};
    2130             :         oid off1, off2;
    2131           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    2132           0 :                 *r = getArgReference_bat(stk, pci, 2),
    2133           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
    2134           0 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    2135             : 
    2136             :         (void) cntxt;
    2137             :         (void) mb;
    2138           0 :         if (!buf) {
    2139           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2140           0 :                 goto bailout;
    2141             :         }
    2142           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
    2143           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2144           0 :                 goto bailout;
    2145             :         }
    2146           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
    2147           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2148           0 :                 goto bailout;
    2149             :         }
    2150           0 :         q = canditer_init(&ci1, left, lefts);
    2151           0 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
    2152           0 :                 msg = createException(MAL, "batstr.unicodeAt", ILLEGAL_ARGUMENT " Requires bats of identical size");
    2153           0 :                 goto bailout;
    2154             :         }
    2155           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    2156           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2157           0 :                 goto bailout;
    2158             :         }
    2159             : 
    2160           0 :         off1 = left->hseqbase;
    2161           0 :         off2 = right->hseqbase;
    2162           0 :         lefti = bat_iterator(left);
    2163           0 :         bi = bat_iterator(right);
    2164           0 :         righti = bi.base;
    2165           0 :         vals = Tloc(bn, 0);
    2166           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    2167           0 :                 for (BUN i = 0; i < q; i++) {
    2168           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    2169           0 :                         x = (str) BUNtvar(lefti, p1);
    2170           0 :                         y = righti[p2];
    2171             : 
    2172           0 :                         if ((msg = str_wchr_at(&next, x, y)) != MAL_SUCCEED)
    2173           0 :                                 goto bailout1;
    2174           0 :                         vals[i] = next;
    2175           0 :                         nils |= is_int_nil(next);
    2176             :                 }
    2177             :         } else {
    2178           0 :                 for (BUN i = 0; i < q; i++) {
    2179           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    2180           0 :                         x = (str) BUNtvar(lefti, p1);
    2181           0 :                         y = righti[p2];
    2182             : 
    2183           0 :                         if ((msg = str_wchr_at(&next, x, y)) != MAL_SUCCEED)
    2184           0 :                                 goto bailout1;
    2185           0 :                         vals[i] = next;
    2186           0 :                         nils |= is_int_nil(next);
    2187             :                 }
    2188             :         }
    2189           0 : bailout1:
    2190           0 :         bat_iterator_end(&bi);
    2191           0 :         bat_iterator_end(&lefti);
    2192           0 : bailout:
    2193           0 :         GDKfree(buf);
    2194           0 :         finalize_ouput(res, bn, msg, nils, q);
    2195           0 :         unfix_inputs(4, left, lefts, right, rights);
    2196           0 :         return msg;
    2197             : }
    2198             : 
    2199             : static str
    2200           0 : STRbatWChrAtcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2201             : {
    2202             :         BATiter bi;
    2203             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2204             :         BUN q = 0;
    2205             :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2206           0 :         int y = *getArgReference_int(stk, pci, 2), *restrict vals, next;
    2207           0 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2208             :         bool nils = false;
    2209           0 :         struct canditer ci1 = {0};
    2210             :         oid off1;
    2211           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    2212           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2213             : 
    2214             :         (void) cntxt;
    2215             :         (void) mb;
    2216           0 :         if (!buf) {
    2217           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2218           0 :                 goto bailout;
    2219             :         }
    2220           0 :         if (!(b = BATdescriptor(*l))) {
    2221           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2222           0 :                 goto bailout;
    2223             :         }
    2224           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2225           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2226           0 :                 goto bailout;
    2227             :         }
    2228           0 :         q = canditer_init(&ci1, b, bs);
    2229           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    2230           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2231           0 :                 goto bailout;
    2232             :         }
    2233             : 
    2234           0 :         off1 = b->hseqbase;
    2235           0 :         bi = bat_iterator(b);
    2236           0 :         vals = Tloc(bn, 0);
    2237           0 :         if (ci1.tpe == cand_dense) {
    2238           0 :                 for (BUN i = 0; i < q; i++) {
    2239           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2240           0 :                         x = (str) BUNtvar(bi, p1);
    2241             : 
    2242           0 :                         if ((msg = str_wchr_at(&next, x, y)) != MAL_SUCCEED)
    2243           0 :                                 goto bailout1;
    2244           0 :                         vals[i] = next;
    2245           0 :                         nils |= is_int_nil(next);
    2246             :                 }
    2247             :         } else {
    2248           0 :                 for (BUN i = 0; i < q; i++) {
    2249           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2250           0 :                         x = (str) BUNtvar(bi, p1);
    2251             : 
    2252           0 :                         if ((msg = str_wchr_at(&next, x, y)) != MAL_SUCCEED)
    2253           0 :                                 goto bailout1;
    2254           0 :                         vals[i] = next;
    2255           0 :                         nils |= is_int_nil(next);
    2256             :                 }
    2257             :         }
    2258           0 : bailout1:
    2259           0 :         bat_iterator_end(&bi);
    2260           0 : bailout:
    2261           0 :         GDKfree(buf);
    2262           0 :         finalize_ouput(res, bn, msg, nils, q);
    2263           0 :         unfix_inputs(2, b, bs);
    2264           0 :         return msg;
    2265             : }
    2266             : 
    2267             : static str
    2268           0 : STRbatWChrAt_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2269             : {
    2270             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2271             :         BUN q = 0;
    2272             :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2273             :         int y, *restrict vals, *restrict input, next;
    2274           0 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2275             :         bool nils = false;
    2276           0 :         struct canditer ci1 = {0};
    2277             :         oid off1;
    2278           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 2),
    2279           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2280             :         BATiter bi;
    2281             : 
    2282             :         (void) cntxt;
    2283             :         (void) mb;
    2284           0 :         if (!buf) {
    2285           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2286           0 :                 goto bailout;
    2287             :         }
    2288           0 :         if (!(b = BATdescriptor(*l))) {
    2289           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2290           0 :                 goto bailout;
    2291             :         }
    2292           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2293           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2294           0 :                 goto bailout;
    2295             :         }
    2296           0 :         q = canditer_init(&ci1, b, bs);
    2297           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    2298           0 :                 msg = createException(MAL, "batstr.unicodeAt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2299           0 :                 goto bailout;
    2300             :         }
    2301             : 
    2302           0 :         off1 = b->hseqbase;
    2303           0 :         bi = bat_iterator(b);
    2304           0 :         input = bi.base;
    2305           0 :         vals = Tloc(bn, 0);
    2306           0 :         if (ci1.tpe == cand_dense) {
    2307           0 :                 for (BUN i = 0; i < q; i++) {
    2308           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2309           0 :                         y = input[p1];
    2310             : 
    2311           0 :                         if ((msg = str_wchr_at(&next, x, y)) != MAL_SUCCEED)
    2312           0 :                                 goto bailout1;
    2313           0 :                         vals[i] = next;
    2314           0 :                         nils |= is_int_nil(next);
    2315             :                 }
    2316             :         } else {
    2317           0 :                 for (BUN i = 0; i < q; i++) {
    2318           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2319           0 :                         y = input[p1];
    2320             : 
    2321           0 :                         if ((msg = str_wchr_at(&next, x, y)) != MAL_SUCCEED)
    2322           0 :                                 goto bailout1;
    2323           0 :                         vals[i] = next;
    2324           0 :                         nils |= is_int_nil(next);
    2325             :                 }
    2326             :         }
    2327           0 : bailout1:
    2328           0 :         bat_iterator_end(&bi);
    2329           0 : bailout:
    2330           0 :         GDKfree(buf);
    2331           0 :         finalize_ouput(res, bn, msg, nils, q);
    2332           0 :         unfix_inputs(2, b, bs);
    2333           0 :         return msg;
    2334             : }
    2335             : 
    2336             : static str
    2337         147 : do_batstr_str_int_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int))
    2338             : {
    2339             :         BATiter bi;
    2340             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2341             :         BUN q = 0;
    2342         147 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2343         147 :         int y = *getArgReference_int(stk, pci, 2);
    2344         147 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2345             :         bool nils = false;
    2346         147 :         struct canditer ci1 = {0};
    2347             :         oid off1;
    2348         147 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    2349         147 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2350             : 
    2351             :         (void) cntxt;
    2352             :         (void) mb;
    2353         147 :         if (!buf) {
    2354           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2355           0 :                 goto bailout;
    2356             :         }
    2357         147 :         if (!(b = BATdescriptor(*l))) {
    2358           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2359           0 :                 goto bailout;
    2360             :         }
    2361         147 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2362           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2363           0 :                 goto bailout;
    2364             :         }
    2365         147 :         q = canditer_init(&ci1, b, bs);
    2366         147 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2367           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2368           0 :                 goto bailout;
    2369             :         }
    2370             : 
    2371         147 :         off1 = b->hseqbase;
    2372         147 :         bi = bat_iterator(b);
    2373         147 :         if (ci1.tpe == cand_dense) {
    2374      162687 :                 for (BUN i = 0; i < q; i++) {
    2375      162540 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2376      162540 :                         x = (str) BUNtvar(bi, p1);
    2377             : 
    2378      162540 :                         if (strNil(x) || is_int_nil(y)) {
    2379           9 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2380           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2381           0 :                                         goto bailout1;
    2382             :                                 }
    2383             :                                 nils = true;
    2384             :                         } else {
    2385      162531 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2386           0 :                                         goto bailout1;
    2387      162531 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2388           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2389           0 :                                         goto bailout1;
    2390             :                                 }
    2391             :                         }
    2392             :                 }
    2393             :         } else {
    2394           0 :                 for (BUN i = 0; i < q; i++) {
    2395           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2396           0 :                         x = (str) BUNtvar(bi, p1);
    2397             : 
    2398           0 :                         if (strNil(x) || is_int_nil(y)) {
    2399           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2400           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2401           0 :                                         goto bailout1;
    2402             :                                 }
    2403             :                                 nils = true;
    2404             :                         } else {
    2405           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2406           0 :                                         goto bailout1;
    2407           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2408           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2409           0 :                                         goto bailout1;
    2410             :                                 }
    2411             :                         }
    2412             :                 }
    2413             :         }
    2414           0 : bailout1:
    2415         147 :         bat_iterator_end(&bi);
    2416         147 : bailout:
    2417         147 :         GDKfree(buf);
    2418         147 :         finalize_ouput(res, bn, msg, nils, q);
    2419         147 :         unfix_inputs(2, b, bs);
    2420         147 :         return msg;
    2421             : }
    2422             : 
    2423             : static str
    2424         137 : STRbatprefixcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2425             : {
    2426         137 :         return do_batstr_str_int_cst(cntxt, mb, stk, pci, "batstr.prefix", str_prefix);
    2427             : }
    2428             : 
    2429             : static str
    2430           1 : STRbatsuffixcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2431             : {
    2432           1 :         return do_batstr_str_int_cst(cntxt, mb, stk, pci, "batstr.suffix", str_suffix);
    2433             : }
    2434             : 
    2435             : static str
    2436           5 : STRbatTailcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2437             : {
    2438           5 :         return do_batstr_str_int_cst(cntxt, mb, stk, pci, "batstr.tail", str_tail);
    2439             : }
    2440             : 
    2441             : static str
    2442           4 : STRbatsubstringTailcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2443             : {
    2444           4 :         return do_batstr_str_int_cst(cntxt, mb, stk, pci, "batstr.substring", str_substring_tail);
    2445             : }
    2446             : 
    2447             : static str
    2448           1 : STRbatrepeatcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2449             : {
    2450             :         BATiter bi;
    2451             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2452             :         BUN q = 0;
    2453           1 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2454           1 :         int y = *getArgReference_int(stk, pci, 2);
    2455           1 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2456             :         bool nils = false;
    2457           1 :         struct canditer ci1 = {0};
    2458             :         oid off1;
    2459           1 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    2460           1 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2461             : 
    2462             :         (void) cntxt;
    2463             :         (void) mb;
    2464           1 :         if (!buf) {
    2465           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2466           0 :                 goto bailout;
    2467             :         }
    2468           1 :         if (!(b = BATdescriptor(*l))) {
    2469           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2470           0 :                 goto bailout;
    2471             :         }
    2472           1 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2473           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2474           0 :                 goto bailout;
    2475             :         }
    2476           1 :         q = canditer_init(&ci1, b, bs);
    2477           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2478           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2479           0 :                 goto bailout;
    2480             :         }
    2481             : 
    2482           1 :         off1 = b->hseqbase;
    2483           1 :         bi = bat_iterator(b);
    2484           1 :         if (ci1.tpe == cand_dense) {
    2485           5 :                 for (BUN i = 0; i < q; i++) {
    2486           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2487           4 :                         x = (str) BUNtvar(bi, p1);
    2488             : 
    2489           4 :                         if (strNil(x) || is_int_nil(y) || y < 0) {
    2490           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2491           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2492           0 :                                         goto bailout1;
    2493             :                                 }
    2494             :                                 nils = true;
    2495             :                         } else {
    2496           4 :                                 if ((msg = str_repeat(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2497           0 :                                         goto bailout1;
    2498           4 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2499           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2500           0 :                                         goto bailout1;
    2501             :                                 }
    2502             :                         }
    2503             :                 }
    2504             :         } else {
    2505           0 :                 for (BUN i = 0; i < q; i++) {
    2506           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2507           0 :                         x = (str) BUNtvar(bi, p1);
    2508             : 
    2509           0 :                         if (strNil(x) || is_int_nil(y) || y < 0) {
    2510           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2511           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2512           0 :                                         goto bailout1;
    2513             :                                 }
    2514             :                                 nils = true;
    2515             :                         } else {
    2516           0 :                                 if ((msg = str_repeat(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2517           0 :                                         goto bailout1;
    2518           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2519           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2520           0 :                                         goto bailout1;
    2521             :                                 }
    2522             :                         }
    2523             :                 }
    2524             :         }
    2525           0 : bailout1:
    2526           1 :         bat_iterator_end(&bi);
    2527           1 : bailout:
    2528           1 :         GDKfree(buf);
    2529           1 :         finalize_ouput(res, bn, msg, nils, q);
    2530           1 :         unfix_inputs(2, b, bs);
    2531           1 :         return msg;
    2532             : }
    2533             : 
    2534             : static str
    2535           5 : do_batstr_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int))
    2536             : {
    2537             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2538             :         BUN q = 0;
    2539           5 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2540             :         int *restrict vals, y;
    2541           5 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2542             :         bool nils = false;
    2543           5 :         struct canditer ci1 = {0};
    2544             :         oid off1;
    2545           5 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 2),
    2546           5 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2547             :         BATiter bi;
    2548             : 
    2549             :         (void) cntxt;
    2550             :         (void) mb;
    2551           5 :         if (!buf) {
    2552           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2553           0 :                 goto bailout;
    2554             :         }
    2555           5 :         if (!(b = BATdescriptor(*l))) {
    2556           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2557           0 :                 goto bailout;
    2558             :         }
    2559           5 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2560           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2561           0 :                 goto bailout;
    2562             :         }
    2563           5 :         q = canditer_init(&ci1, b, bs);
    2564           5 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2565           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2566           0 :                 goto bailout;
    2567             :         }
    2568             : 
    2569           5 :         off1 = b->hseqbase;
    2570           5 :         bi = bat_iterator(b);
    2571           5 :         vals = bi.base;
    2572           5 :         if (ci1.tpe == cand_dense) {
    2573          10 :                 for (BUN i = 0; i < q; i++) {
    2574           5 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2575           5 :                         y = vals[p1];
    2576             : 
    2577           5 :                         if (strNil(x) || is_int_nil(y)) {
    2578           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2579           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2580           0 :                                         goto bailout1;
    2581             :                                 }
    2582             :                                 nils = true;
    2583             :                         } else {
    2584           5 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2585           0 :                                         goto bailout1;
    2586           5 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2587           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2588           0 :                                         goto bailout1;
    2589             :                                 }
    2590             :                         }
    2591             :                 }
    2592             :         } else {
    2593           0 :                 for (BUN i = 0; i < q; i++) {
    2594           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2595           0 :                         y = vals[p1];
    2596             : 
    2597           0 :                         if (strNil(x) || is_int_nil(y)) {
    2598           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2599           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2600           0 :                                         goto bailout1;
    2601             :                                 }
    2602             :                                 nils = true;
    2603             :                         } else {
    2604           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2605           0 :                                         goto bailout1;
    2606           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2607           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2608           0 :                                         goto bailout1;
    2609             :                                 }
    2610             :                         }
    2611             :                 }
    2612             :         }
    2613           0 : bailout1:
    2614           5 :         bat_iterator_end(&bi);
    2615           5 : bailout:
    2616           5 :         GDKfree(buf);
    2617           5 :         finalize_ouput(res, bn, msg, nils, q);
    2618           5 :         unfix_inputs(2, b, bs);
    2619           5 :         return msg;
    2620             : }
    2621             : 
    2622             : static str
    2623           4 : STRbatprefix_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2624             : {
    2625           4 :         return do_batstr_strcst(cntxt, mb, stk, pci, "batstr.prefix", str_prefix);
    2626             : }
    2627             : 
    2628             : static str
    2629           1 : STRbatsuffix_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2630             : {
    2631           1 :         return do_batstr_strcst(cntxt, mb, stk, pci, "batstr.suffix", str_suffix);
    2632             : }
    2633             : 
    2634             : static str
    2635           0 : STRbatTail_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2636             : {
    2637           0 :         return do_batstr_strcst(cntxt, mb, stk, pci, "batstr.tail", str_tail);
    2638             : }
    2639             : 
    2640             : static str
    2641           0 : STRbatsubstringTail_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2642             : {
    2643           0 :         return do_batstr_strcst(cntxt, mb, stk, pci, "batstr.substring", str_substring_tail);
    2644             : }
    2645             : 
    2646             : static str
    2647           0 : STRbatrepeat_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2648             : {
    2649             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2650             :         BUN q = 0;
    2651           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2652             :         int *restrict vals, y;
    2653           0 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2654             :         bool nils = false;
    2655           0 :         struct canditer ci1 = {0};
    2656             :         oid off1;
    2657           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 2),
    2658           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    2659             :         BATiter bi;
    2660             : 
    2661             :         (void) cntxt;
    2662             :         (void) mb;
    2663           0 :         if (!buf) {
    2664           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2665           0 :                 goto bailout;
    2666             :         }
    2667           0 :         if (!(b = BATdescriptor(*l))) {
    2668           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2669           0 :                 goto bailout;
    2670             :         }
    2671           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2672           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2673           0 :                 goto bailout;
    2674             :         }
    2675           0 :         q = canditer_init(&ci1, b, bs);
    2676           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2677           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2678           0 :                 goto bailout;
    2679             :         }
    2680             : 
    2681           0 :         off1 = b->hseqbase;
    2682           0 :         bi = bat_iterator(b);
    2683           0 :         vals = bi.base;
    2684           0 :         if (ci1.tpe == cand_dense) {
    2685           0 :                 for (BUN i = 0; i < q; i++) {
    2686           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2687           0 :                         y = vals[p1];
    2688             : 
    2689           0 :                         if (strNil(x) || is_int_nil(y) || y < 0) {
    2690           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2691           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2692           0 :                                         goto bailout1;
    2693             :                                 }
    2694             :                                 nils = true;
    2695             :                         } else {
    2696           0 :                                 if ((msg = str_repeat(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2697           0 :                                         goto bailout1;
    2698           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2699           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2700           0 :                                         goto bailout1;
    2701             :                                 }
    2702             :                         }
    2703             :                 }
    2704             :         } else {
    2705           0 :                 for (BUN i = 0; i < q; i++) {
    2706           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    2707           0 :                         y = vals[p1];
    2708             : 
    2709           0 :                         if (strNil(x) || is_int_nil(y) || y < 0) {
    2710           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2711           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2712           0 :                                         goto bailout1;
    2713             :                                 }
    2714             :                                 nils = true;
    2715             :                         } else {
    2716           0 :                                 if ((msg = str_repeat(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2717           0 :                                         goto bailout1;
    2718           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2719           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2720           0 :                                         goto bailout1;
    2721             :                                 }
    2722             :                         }
    2723             :                 }
    2724             :         }
    2725           0 : bailout1:
    2726           0 :         bat_iterator_end(&bi);
    2727           0 : bailout:
    2728           0 :         GDKfree(buf);
    2729           0 :         finalize_ouput(res, bn, msg, nils, q);
    2730           0 :         unfix_inputs(2, b, bs);
    2731           0 :         return msg;
    2732             : }
    2733             : 
    2734             : static str
    2735           1 : do_batstr_str_int(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *name, str (*func)(str*, size_t*, str, int))
    2736             : {
    2737             :         BATiter lefti;
    2738             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
    2739             :         BUN q = 0;
    2740           1 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2741             :         int *restrict righti, y;
    2742           1 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2743             :         bool nils = false;
    2744           1 :         struct canditer ci1 = {0}, ci2 = {0};
    2745             :         oid off1, off2;
    2746           1 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    2747           1 :                 *r = getArgReference_bat(stk, pci, 2),
    2748           1 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
    2749           1 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    2750             :         BATiter bi;
    2751             : 
    2752             :         (void) cntxt;
    2753             :         (void) mb;
    2754           1 :         if (!buf) {
    2755           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2756           0 :                 goto bailout;
    2757             :         }
    2758           1 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
    2759           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2760           0 :                 goto bailout;
    2761             :         }
    2762           1 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
    2763           0 :                 msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2764           0 :                 goto bailout;
    2765             :         }
    2766           1 :         q = canditer_init(&ci1, left, lefts);
    2767           1 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
    2768           0 :                 msg = createException(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size");
    2769           0 :                 goto bailout;
    2770             :         }
    2771           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2772           0 :                 msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2773           0 :                 goto bailout;
    2774             :         }
    2775             : 
    2776           1 :         off1 = left->hseqbase;
    2777           1 :         off2 = right->hseqbase;
    2778           1 :         lefti = bat_iterator(left);
    2779           1 :         bi = bat_iterator(right);
    2780           1 :         righti = bi.base;
    2781           1 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    2782           2 :                 for (BUN i = 0; i < q; i++) {
    2783           1 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    2784           1 :                         x = (str) BUNtvar(lefti, p1);
    2785           1 :                         y = righti[p2];
    2786             : 
    2787           1 :                         if (strNil(x) || is_int_nil(y)) {
    2788           1 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2789           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2790           0 :                                         goto bailout1;
    2791             :                                 }
    2792             :                                 nils = true;
    2793             :                         } else {
    2794           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2795           0 :                                         goto bailout1;
    2796           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2797           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2798           0 :                                         goto bailout1;
    2799             :                                 }
    2800             :                         }
    2801             :                 }
    2802             :         } else {
    2803           0 :                 for (BUN i = 0; i < q; i++) {
    2804           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    2805           0 :                         x = (str) BUNtvar(lefti, p1);
    2806           0 :                         y = righti[p2];
    2807             : 
    2808           0 :                         if (strNil(x) || is_int_nil(y)) {
    2809           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2810           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2811           0 :                                         goto bailout1;
    2812             :                                 }
    2813             :                                 nils = true;
    2814             :                         } else {
    2815           0 :                                 if ((msg = (*func)(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2816           0 :                                         goto bailout1;
    2817           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2818           0 :                                         msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2819           0 :                                         goto bailout1;
    2820             :                                 }
    2821             :                         }
    2822             :                 }
    2823             :         }
    2824           0 : bailout1:
    2825           1 :         bat_iterator_end(&bi);
    2826           1 :         bat_iterator_end(&lefti);
    2827           1 : bailout:
    2828           1 :         GDKfree(buf);
    2829           1 :         finalize_ouput(res, bn, msg, nils, q);
    2830           1 :         unfix_inputs(4, left, lefts, right, rights);
    2831           1 :         return msg;
    2832             : }
    2833             : 
    2834             : static str
    2835           0 : STRbatprefix(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2836             : {
    2837           0 :         return do_batstr_str_int(cntxt, mb, stk, pci, "batstr.prefix", str_prefix);
    2838             : }
    2839             : 
    2840             : static str
    2841           0 : STRbatsuffix(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2842             : {
    2843           0 :         return do_batstr_str_int(cntxt, mb, stk, pci, "batstr.suffix", str_suffix);
    2844             : }
    2845             : 
    2846             : static str
    2847           0 : STRbatTail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2848             : {
    2849           0 :         return do_batstr_str_int(cntxt, mb, stk, pci, "batstr.tail", str_tail);
    2850             : }
    2851             : 
    2852             : static str
    2853           1 : STRbatsubstringTail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2854             : {
    2855           1 :         return do_batstr_str_int(cntxt, mb, stk, pci, "batstr.substring", str_substring_tail);
    2856             : }
    2857             : 
    2858             : static str
    2859           0 : STRbatrepeat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2860             : {
    2861             :         BATiter lefti;
    2862             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
    2863             :         BUN q = 0;
    2864           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2865             :         int *restrict righti, y;
    2866           0 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2867             :         bool nils = false;
    2868           0 :         struct canditer ci1 = {0}, ci2 = {0};
    2869             :         oid off1, off2;
    2870           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    2871           0 :                 *r = getArgReference_bat(stk, pci, 2),
    2872           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
    2873           0 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    2874             :         BATiter bi;
    2875             : 
    2876             :         (void) cntxt;
    2877             :         (void) mb;
    2878           0 :         if (!buf) {
    2879           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2880           0 :                 goto bailout;
    2881             :         }
    2882           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
    2883           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2884           0 :                 goto bailout;
    2885             :         }
    2886           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
    2887           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2888           0 :                 goto bailout;
    2889             :         }
    2890           0 :         q = canditer_init(&ci1, left, lefts);
    2891           0 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
    2892           0 :                 msg = createException(MAL, "batstr.repeat", ILLEGAL_ARGUMENT " Requires bats of identical size");
    2893           0 :                 goto bailout;
    2894             :         }
    2895           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2896           0 :                 msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2897           0 :                 goto bailout;
    2898             :         }
    2899             : 
    2900           0 :         off1 = left->hseqbase;
    2901           0 :         off2 = right->hseqbase;
    2902           0 :         lefti = bat_iterator(left);
    2903           0 :         bi = bat_iterator(right);
    2904           0 :         righti = bi.base;
    2905           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    2906           0 :                 for (BUN i = 0; i < q; i++) {
    2907           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    2908           0 :                         x = (str) BUNtvar(lefti, p1);
    2909           0 :                         y = righti[p2];
    2910             : 
    2911           0 :                         if (strNil(x) || is_int_nil(y) || y < 0) {
    2912           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2913           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2914           0 :                                         goto bailout1;
    2915             :                                 }
    2916             :                                 nils = true;
    2917             :                         } else {
    2918           0 :                                 if ((msg = str_repeat(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2919           0 :                                         goto bailout1;
    2920           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2921           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2922           0 :                                         goto bailout1;
    2923             :                                 }
    2924             :                         }
    2925             :                 }
    2926             :         } else {
    2927           0 :                 for (BUN i = 0; i < q; i++) {
    2928           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    2929           0 :                         x = (str) BUNtvar(lefti, p1);
    2930           0 :                         y = righti[p2];
    2931             : 
    2932           0 :                         if (strNil(x) || is_int_nil(y) || y < 0) {
    2933           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    2934           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2935           0 :                                         goto bailout1;
    2936             :                                 }
    2937             :                                 nils = true;
    2938             :                         } else {
    2939           0 :                                 if ((msg = str_repeat(&buf, &buflen, x, y)) != MAL_SUCCEED)
    2940           0 :                                         goto bailout1;
    2941           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    2942           0 :                                         msg = createException(MAL, "batstr.repeat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2943           0 :                                         goto bailout1;
    2944             :                                 }
    2945             :                         }
    2946             :                 }
    2947             :         }
    2948           0 : bailout1:
    2949           0 :         bat_iterator_end(&bi);
    2950           0 :         bat_iterator_end(&lefti);
    2951           0 : bailout:
    2952           0 :         GDKfree(buf);
    2953           0 :         finalize_ouput(res, bn, msg, nils, q);
    2954           0 :         unfix_inputs(4, left, lefts, right, rights);
    2955           0 :         return msg;
    2956             : }
    2957             : 
    2958             : static str
    2959         270 : STRbatSubstitutecst_imp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int cand_nargs, const bit *rep)
    2960             : {
    2961             :         BATiter bi;
    2962             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    2963             :         BUN q = 0;
    2964         270 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    2965         270 :         str x, y = *getArgReference_str(stk, pci, 2), z = *getArgReference_str(stk, pci, 3), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    2966             :         bool nils = false;
    2967         270 :         bit w = *rep;
    2968         270 :         struct canditer ci1 = {0};
    2969             :         oid off1;
    2970         270 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    2971         270 :                 *sid1 = pci->argc == cand_nargs ? getArgReference_bat(stk, pci, cand_nargs - 1) : NULL;
    2972             : 
    2973         270 :         if (!buf) {
    2974           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2975           0 :                 goto bailout;
    2976             :         }
    2977         270 :         if (!(b = BATdescriptor(*bid))) {
    2978           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2979           0 :                 goto bailout;
    2980             :         }
    2981         270 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    2982           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    2983           0 :                 goto bailout;
    2984             :         }
    2985         270 :         q = canditer_init(&ci1, b, bs);
    2986         270 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    2987           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2988           0 :                 goto bailout;
    2989             :         }
    2990             : 
    2991             :         (void) cntxt;
    2992             :         (void) mb;
    2993         270 :         off1 = b->hseqbase;
    2994         270 :         bi = bat_iterator(b);
    2995         270 :         if (ci1.tpe == cand_dense) {
    2996       78100 :                 for (BUN i = 0; i < q; i++) {
    2997       77830 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    2998       77830 :                         x = (str) BUNtvar(bi, p1);
    2999             : 
    3000      231708 :                         if (strNil(x) || strNil(y) || strNil(z) || is_bit_nil(w)) {
    3001         892 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3002           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3003           0 :                                         goto bailout1;
    3004             :                                 }
    3005             :                                 nils = true;
    3006             :                         } else {
    3007       76938 :                                 if ((msg = str_substitute(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3008           0 :                                         goto bailout1;
    3009       76938 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3010           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3011           0 :                                         goto bailout1;
    3012             :                                 }
    3013             :                         }
    3014             :                 }
    3015             :         } else {
    3016           0 :                 for (BUN i = 0; i < q; i++) {
    3017           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    3018           0 :                         x = (str) BUNtvar(bi, p1);
    3019             : 
    3020           0 :                         if (strNil(x) || strNil(y) || strNil(z) || is_bit_nil(w)) {
    3021           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3022           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3023           0 :                                         goto bailout1;
    3024             :                                 }
    3025             :                                 nils = true;
    3026             :                         } else {
    3027           0 :                                 if ((msg = str_substitute(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3028           0 :                                         goto bailout1;
    3029           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3030           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3031           0 :                                         goto bailout1;
    3032             :                                 }
    3033             :                         }
    3034             :                 }
    3035             :         }
    3036           0 : bailout1:
    3037         270 :         bat_iterator_end(&bi);
    3038         270 : bailout:
    3039         270 :         GDKfree(buf);
    3040         270 :         finalize_ouput(res, bn, msg, nils, q);
    3041         270 :         unfix_inputs(2, b, bs);
    3042         270 :         return msg;
    3043             : }
    3044             : 
    3045             : static str
    3046           0 : STRbatSubstitutecst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3047             : {
    3048           0 :         const bit *rep = getArgReference_bit(stk, pci, 0);
    3049           0 :         return STRbatSubstitutecst_imp(cntxt, mb, stk, pci, 6, rep);
    3050             : }
    3051             : 
    3052             : static str
    3053           0 : STRbatSubstitute(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3054             : {
    3055             :         BATiter arg1i, arg2i, arg3i;
    3056             :         BAT *bn = NULL, *arg1 = NULL, *arg1s = NULL, *arg2 = NULL, *arg2s = NULL, *arg3 = NULL, *arg3s = NULL, *arg4 = NULL, *arg4s = NULL;
    3057             :         BUN q = 0;
    3058           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3059           0 :         str x, y, z, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3060             :         bool nils = false;
    3061             :         bit *restrict arg4i, w;
    3062           0 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0}, ci4 = {0};
    3063             :         oid off1, off2, off3, off4;
    3064           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    3065           0 :                 *r = getArgReference_bat(stk, pci, 2), *s = getArgReference_bat(stk, pci, 3),
    3066           0 :                 *rep = getArgReference_bat(stk, pci, 4),
    3067           0 :                 *sid1 = pci->argc == 9 ? getArgReference_bat(stk, pci, 5) : NULL,
    3068           0 :                 *sid2 = pci->argc == 9 ? getArgReference_bat(stk, pci, 6) : NULL,
    3069           0 :                 *sid3 = pci->argc == 9 ? getArgReference_bat(stk, pci, 7) : NULL,
    3070           0 :                 *sid4 = pci->argc == 9 ? getArgReference_bat(stk, pci, 8) : NULL;
    3071             :         BATiter bi;
    3072             : 
    3073           0 :         if (!buf) {
    3074           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3075           0 :                 goto bailout;
    3076             :         }
    3077           0 :         if (!(arg1 = BATdescriptor(*l)) || !(arg2 = BATdescriptor(*r)) || !(arg3 = BATdescriptor(*s)) || !(arg4 = BATdescriptor(*rep))) {
    3078           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3079           0 :                 goto bailout;
    3080             :         }
    3081           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(arg1s = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(arg2s = BATdescriptor(*sid2))) ||
    3082           0 :                 (sid3 && !is_bat_nil(*sid3) && !(arg2s = BATdescriptor(*sid3))) || (sid4 && !is_bat_nil(*sid4) && !(arg4s = BATdescriptor(*sid4)))) {
    3083           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3084           0 :                 goto bailout;
    3085             :         }
    3086           0 :         q = canditer_init(&ci1, arg1, arg1s);
    3087           0 :         if (canditer_init(&ci2, arg2, arg2s) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, arg3, arg3s) != q ||
    3088           0 :                 ci2.hseq != ci3.hseq || canditer_init(&ci4, arg4, arg4s) != q || ci3.hseq != ci4.hseq) {
    3089           0 :                 msg = createException(MAL, "batstr.substritute", ILLEGAL_ARGUMENT " Requires bats of identical size");
    3090           0 :                 goto bailout;
    3091             :         }
    3092           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3093           0 :                 msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3094           0 :                 goto bailout;
    3095             :         }
    3096             : 
    3097             :         (void) cntxt;
    3098             :         (void) mb;
    3099           0 :         off1 = arg1->hseqbase;
    3100           0 :         off2 = arg2->hseqbase;
    3101           0 :         off3 = arg3->hseqbase;
    3102           0 :         off4 = arg4->hseqbase;
    3103           0 :         arg1i = bat_iterator(arg1);
    3104           0 :         arg2i = bat_iterator(arg2);
    3105           0 :         arg3i = bat_iterator(arg3);
    3106           0 :         bi = bat_iterator(arg4);
    3107           0 :         arg4i = bi.base;
    3108           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense && ci4.tpe == cand_dense) {
    3109           0 :                 for (BUN i = 0; i < q; i++) {
    3110           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2),
    3111           0 :                                 p3 = (canditer_next_dense(&ci3) - off3), p4 = (canditer_next_dense(&ci4) - off4);
    3112           0 :                         x = (str) BUNtvar(arg1i, p1);
    3113           0 :                         y = (str) BUNtvar(arg2i, p2);
    3114           0 :                         z = (str) BUNtvar(arg3i, p3);
    3115           0 :                         w = arg4i[p4];
    3116             : 
    3117           0 :                         if (strNil(x) || strNil(y) || strNil(z) || is_bit_nil(w)) {
    3118           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3119           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3120           0 :                                         goto bailout1;
    3121             :                                 }
    3122             :                                 nils = true;
    3123             :                         } else {
    3124           0 :                                 if ((msg = str_substitute(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3125           0 :                                         goto bailout1;
    3126           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3127           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3128           0 :                                         goto bailout1;
    3129             :                                 }
    3130             :                         }
    3131             :                 }
    3132             :         } else {
    3133           0 :                 for (BUN i = 0; i < q; i++) {
    3134           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2),
    3135           0 :                                 p3 = (canditer_next(&ci3) - off3), p4 = (canditer_next(&ci4) - off4);
    3136           0 :                         x = (str) BUNtvar(arg1i, p1);
    3137           0 :                         y = (str) BUNtvar(arg2i, p2);
    3138           0 :                         z = (str) BUNtvar(arg3i, p3);
    3139           0 :                         w = arg4i[p4];
    3140             : 
    3141           0 :                         if (strNil(x) || strNil(y) || strNil(z) || is_bit_nil(w)) {
    3142           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3143           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3144           0 :                                         goto bailout1;
    3145             :                                 }
    3146             :                                 nils = true;
    3147             :                         } else {
    3148           0 :                                 if ((msg = str_substitute(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3149           0 :                                         goto bailout1;
    3150           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3151           0 :                                         msg = createException(MAL, "batstr.substritute", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3152           0 :                                         goto bailout1;
    3153             :                                 }
    3154             :                         }
    3155             :                 }
    3156             :         }
    3157           0 : bailout1:
    3158           0 :         bat_iterator_end(&bi);
    3159           0 :         bat_iterator_end(&arg1i);
    3160           0 :         bat_iterator_end(&arg2i);
    3161           0 :         bat_iterator_end(&arg3i);
    3162           0 : bailout:
    3163           0 :         GDKfree(buf);
    3164           0 :         finalize_ouput(res, bn, msg, nils, q);
    3165           0 :         unfix_inputs(8, arg1, arg1, arg2, arg2s, arg3, arg3s, arg4, arg4s);
    3166           0 :         return msg;
    3167             : }
    3168             : 
    3169             : static str
    3170           2 : STRbatsplitpartcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3171             : {
    3172             :         BATiter bi;
    3173             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    3174             :         BUN q = 0;
    3175           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3176           2 :         int z = *getArgReference_int(stk, pci, 3);
    3177           2 :         str x, y = *getArgReference_str(stk, pci, 2), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3178             :         bool nils = false;
    3179           2 :         struct canditer ci1 = {0};
    3180             :         oid off1;
    3181           2 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    3182           2 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    3183             : 
    3184             :         (void) cntxt;
    3185             :         (void) mb;
    3186           2 :         if (!buf) {
    3187           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3188           0 :                 goto bailout;
    3189             :         }
    3190           2 :         if (!(b = BATdescriptor(*bid))) {
    3191           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3192           0 :                 goto bailout;
    3193             :         }
    3194           2 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    3195           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3196           0 :                 goto bailout;
    3197             :         }
    3198           2 :         q = canditer_init(&ci1, b, bs);
    3199           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3200           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3201           0 :                 goto bailout;
    3202             :         }
    3203             : 
    3204           2 :         off1 = b->hseqbase;
    3205           2 :         bi = bat_iterator(b);
    3206           2 :         if (ci1.tpe == cand_dense) {
    3207          16 :                 for (BUN i = 0; i < q; i++) {
    3208          14 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    3209          14 :                         x = (str) BUNtvar(bi, p1);
    3210             : 
    3211          28 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3212           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3213           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3214           0 :                                         goto bailout1;
    3215             :                                 }
    3216             :                                 nils = true;
    3217             :                         } else {
    3218          14 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3219           0 :                                         goto bailout1;
    3220          14 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3221           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3222           0 :                                         goto bailout1;
    3223             :                                 }
    3224             :                         }
    3225             :                 }
    3226             :         } else {
    3227           0 :                 for (BUN i = 0; i < q; i++) {
    3228           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    3229           0 :                         x = (str) BUNtvar(bi, p1);
    3230             : 
    3231           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3232           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3233           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3234           0 :                                         goto bailout1;
    3235             :                                 }
    3236             :                                 nils = true;
    3237             :                         } else {
    3238           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3239           0 :                                         goto bailout1;
    3240           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3241           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3242           0 :                                         goto bailout1;
    3243             :                                 }
    3244             :                         }
    3245             :                 }
    3246             :         }
    3247           0 : bailout1:
    3248           2 :         bat_iterator_end(&bi);
    3249           2 : bailout:
    3250           2 :         GDKfree(buf);
    3251           2 :         finalize_ouput(res, bn, msg, nils, q);
    3252           2 :         unfix_inputs(2, b, bs);
    3253           2 :         return msg;
    3254             : }
    3255             : 
    3256             : static str
    3257           0 : STRbatsplitpart_needlecst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3258             : {
    3259             :         BATiter bi, fi;
    3260             :         BAT *bn = NULL, *b = NULL, *bs = NULL, *f = NULL, *fs = NULL;
    3261             :         BUN q = 0;
    3262           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3263             :         int *restrict field, z;
    3264           0 :         str x, y = *getArgReference_str(stk, pci, 2), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3265             :         bool nils = false;
    3266           0 :         struct canditer ci1 = {0}, ci2 = {0};
    3267             :         oid off1, off2;
    3268           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    3269           0 :                 *fid = getArgReference_bat(stk, pci, 3),
    3270           0 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    3271           0 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    3272             : 
    3273           0 :         if (!buf) {
    3274           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3275           0 :                 goto bailout;
    3276             :         }
    3277           0 :         if (!(b = BATdescriptor(*bid)) || !(f = BATdescriptor(*fid))) {
    3278           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3279           0 :                 goto bailout;
    3280             :         }
    3281           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(fs = BATdescriptor(*sid2)))) {
    3282           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3283           0 :                 goto bailout;
    3284             :         }
    3285           0 :         q = canditer_init(&ci1, b, bs);
    3286           0 :         if (canditer_init(&ci2, f, fs) != q || ci1.hseq != ci2.hseq) {
    3287           0 :                 msg = createException(MAL, "batstr.splitpart", ILLEGAL_ARGUMENT " Requires bats of identical size");
    3288           0 :                 goto bailout;
    3289             :         }
    3290           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3291           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3292           0 :                 goto bailout;
    3293             :         }
    3294             : 
    3295             :         (void) cntxt;
    3296             :         (void) mb;
    3297           0 :         off1 = b->hseqbase;
    3298           0 :         off2 = f->hseqbase;
    3299           0 :         bi = bat_iterator(b);
    3300           0 :         fi = bat_iterator(f);
    3301           0 :         field = fi.base;
    3302           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    3303           0 :                 for (BUN i = 0; i < q; i++) {
    3304           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    3305           0 :                         x = (str) BUNtvar(bi, p1);
    3306           0 :                         z = field[p2];
    3307             : 
    3308           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3309           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3310           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3311           0 :                                         goto bailout1;
    3312             :                                 }
    3313             :                                 nils = true;
    3314             :                         } else {
    3315           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3316           0 :                                         goto bailout1;
    3317           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3318           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3319           0 :                                         goto bailout1;
    3320             :                                 }
    3321             :                         }
    3322             :                 }
    3323             :         } else {
    3324           0 :                 for (BUN i = 0; i < q; i++) {
    3325           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    3326           0 :                         x = (str) BUNtvar(bi, p1);
    3327           0 :                         z = field[p2];
    3328             : 
    3329           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3330           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3331           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3332           0 :                                         goto bailout1;
    3333             :                                 }
    3334             :                                 nils = true;
    3335             :                         } else {
    3336           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3337           0 :                                         goto bailout1;
    3338           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3339           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3340           0 :                                         goto bailout1;
    3341             :                                 }
    3342             :                         }
    3343             :                 }
    3344             :         }
    3345           0 : bailout1:
    3346           0 :         bat_iterator_end(&fi);
    3347           0 :         bat_iterator_end(&bi);
    3348           0 : bailout:
    3349           0 :         GDKfree(buf);
    3350           0 :         finalize_ouput(res, bn, msg, nils, q);
    3351           0 :         unfix_inputs(4, b, bs, f, fs);
    3352           0 :         return msg;
    3353             : }
    3354             : 
    3355             : static str
    3356           0 : STRbatsplitpart_fieldcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3357             : {
    3358             :         BATiter bi, ni;
    3359             :         BAT *bn = NULL, *b = NULL, *bs = NULL, *n = NULL, *ns = NULL;
    3360             :         BUN q = 0;
    3361           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3362           0 :         int z = *getArgReference_int(stk, pci, 3);
    3363           0 :         str x, y, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3364             :         bool nils = false;
    3365           0 :         struct canditer ci1 = {0}, ci2 = {0};
    3366             :         oid off1, off2;
    3367           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    3368           0 :                 *nid = getArgReference_bat(stk, pci, 2),
    3369           0 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    3370           0 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    3371             : 
    3372             :         (void) cntxt;
    3373             :         (void) mb;
    3374           0 :         if (!buf) {
    3375           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3376           0 :                 goto bailout;
    3377             :         }
    3378           0 :         if (!(b = BATdescriptor(*bid)) || !(n = BATdescriptor(*nid))) {
    3379           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3380           0 :                 goto bailout;
    3381             :         }
    3382           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(ns = BATdescriptor(*sid2)))) {
    3383           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3384           0 :                 goto bailout;
    3385             :         }
    3386           0 :         q = canditer_init(&ci1, b, bs);
    3387           0 :         if (canditer_init(&ci2, n, ns) != q || ci1.hseq != ci2.hseq) {
    3388           0 :                 msg = createException(MAL, "batstr.splitpart", ILLEGAL_ARGUMENT " Requires bats of identical size");
    3389           0 :                 goto bailout;
    3390             :         }
    3391           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3392           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3393           0 :                 goto bailout;
    3394             :         }
    3395             : 
    3396           0 :         off1 = b->hseqbase;
    3397           0 :         off2 = n->hseqbase;
    3398           0 :         bi = bat_iterator(b);
    3399           0 :         ni = bat_iterator(n);
    3400           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    3401           0 :                 for (BUN i = 0; i < q; i++) {
    3402           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    3403           0 :                         x = (str) BUNtvar(bi, p1);
    3404           0 :                         y = (str) BUNtvar(ni, p2);
    3405             : 
    3406           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3407           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3408           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3409           0 :                                         goto bailout1;
    3410             :                                 }
    3411             :                                 nils = true;
    3412             :                         } else {
    3413           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3414           0 :                                         goto bailout1;
    3415           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3416           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3417           0 :                                         goto bailout1;
    3418             :                                 }
    3419             :                         }
    3420             :                 }
    3421             :         } else {
    3422           0 :                 for (BUN i = 0; i < q; i++) {
    3423           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    3424           0 :                         x = (str) BUNtvar(bi, p1);
    3425           0 :                         y = (str) BUNtvar(ni, p2);
    3426             : 
    3427           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3428           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3429           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3430           0 :                                         goto bailout1;
    3431             :                                 }
    3432             :                                 nils = true;
    3433             :                         } else {
    3434           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3435           0 :                                         goto bailout1;
    3436           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3437           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3438           0 :                                         goto bailout1;
    3439             :                                 }
    3440             :                         }
    3441             :                 }
    3442             :         }
    3443           0 : bailout1:
    3444           0 :         bat_iterator_end(&bi);
    3445           0 :         bat_iterator_end(&ni);
    3446           0 : bailout:
    3447           0 :         GDKfree(buf);
    3448           0 :         finalize_ouput(res, bn, msg, nils, q);
    3449           0 :         unfix_inputs(4, b, bs, n, ns);
    3450           0 :         return msg;
    3451             : }
    3452             : 
    3453             : static str
    3454           0 : STRbatsplitpart(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3455             : {
    3456             :         BATiter arg1i, arg2i;
    3457             :         BAT *bn = NULL, *arg1 = NULL, *arg1s = NULL, *arg2 = NULL, *arg2s = NULL, *arg3 = NULL, *arg3s = NULL;
    3458             :         BUN q = 0;
    3459           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3460             :         int *restrict arg3i, z;
    3461           0 :         str x, y, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3462             :         bool nils = false;
    3463           0 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0};
    3464             :         oid off1, off2, off3;
    3465           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    3466           0 :                 *r = getArgReference_bat(stk, pci, 2), *t = getArgReference_bat(stk, pci, 3),
    3467           0 :                 *sid1 = pci->argc == 7 ? getArgReference_bat(stk, pci, 4) : NULL,
    3468           0 :                 *sid2 = pci->argc == 7 ? getArgReference_bat(stk, pci, 5) : NULL,
    3469           0 :                 *sid3 = pci->argc == 7 ? getArgReference_bat(stk, pci, 6) : NULL;
    3470             :         BATiter bi;
    3471             : 
    3472             :         (void) cntxt;
    3473             :         (void) mb;
    3474           0 :         if (!buf) {
    3475           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3476           0 :                 goto bailout;
    3477             :         }
    3478           0 :         if (!(arg1 = BATdescriptor(*l)) || !(arg2 = BATdescriptor(*r)) || !(arg3 = BATdescriptor(*t))) {
    3479           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3480           0 :                 goto bailout;
    3481             :         }
    3482           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(arg1s = BATdescriptor(*sid1))) ||
    3483           0 :                 (sid2 && !is_bat_nil(*sid2) && !(arg2s = BATdescriptor(*sid2))) || (sid3 && !is_bat_nil(*sid3) && !(arg3s = BATdescriptor(*sid3)))) {
    3484           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3485           0 :                 goto bailout;
    3486             :         }
    3487           0 :         q = canditer_init(&ci1, arg1, arg1s);
    3488           0 :         if (canditer_init(&ci2, arg2, arg2s) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, arg3, arg3s) != q || ci2.hseq != ci3.hseq) {
    3489           0 :                 msg = createException(MAL, "batstr.splitpart", ILLEGAL_ARGUMENT " Requires bats of identical size");
    3490           0 :                 goto bailout;
    3491             :         }
    3492           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3493           0 :                 msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3494           0 :                 goto bailout;
    3495             :         }
    3496             : 
    3497           0 :         off1 = arg1->hseqbase;
    3498           0 :         off2 = arg2->hseqbase;
    3499           0 :         off3 = arg3->hseqbase;
    3500           0 :         arg1i = bat_iterator(arg1);
    3501           0 :         arg2i = bat_iterator(arg2);
    3502           0 :         bi = bat_iterator(arg3);
    3503           0 :         arg3i = bi.base;
    3504           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense) {
    3505           0 :                 for (BUN i = 0; i < q; i++) {
    3506           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2), p3 = (canditer_next_dense(&ci3) - off3);
    3507           0 :                         x = (str) BUNtvar(arg1i, p1);
    3508           0 :                         y = (str) BUNtvar(arg2i, p2);
    3509           0 :                         z = arg3i[p3];
    3510             : 
    3511           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3512           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3513           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3514           0 :                                         goto bailout1;
    3515             :                                 }
    3516             :                                 nils = true;
    3517             :                         } else {
    3518           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3519           0 :                                         goto bailout1;
    3520           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3521           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3522           0 :                                         goto bailout1;
    3523             :                                 }
    3524             :                         }
    3525             :                 }
    3526             :         } else {
    3527           0 :                 for (BUN i = 0; i < q; i++) {
    3528           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2), p3 = (canditer_next(&ci3) - off3);
    3529           0 :                         x = (str) BUNtvar(arg1i, p1);
    3530           0 :                         y = (str) BUNtvar(arg2i, p2);
    3531           0 :                         z = arg3i[p3];
    3532             : 
    3533           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    3534           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3535           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3536           0 :                                         goto bailout1;
    3537             :                                 }
    3538             :                                 nils = true;
    3539             :                         } else {
    3540           0 :                                 if ((msg = str_splitpart(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3541           0 :                                         goto bailout1;
    3542           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3543           0 :                                         msg = createException(MAL, "batstr.splitpart", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3544           0 :                                         goto bailout1;
    3545             :                                 }
    3546             :                         }
    3547             :                 }
    3548             :         }
    3549           0 : bailout1:
    3550           0 :         bat_iterator_end(&bi);
    3551           0 :         bat_iterator_end(&arg1i);
    3552           0 :         bat_iterator_end(&arg2i);
    3553           0 : bailout:
    3554           0 :         GDKfree(buf);
    3555           0 :         finalize_ouput(res, bn, msg, nils, q);
    3556           0 :         unfix_inputs(6, arg1, arg1s, arg2, arg2s, arg3, arg3s);
    3557           0 :         return msg;
    3558             : }
    3559             : 
    3560             : static str
    3561         270 : STRbatReplacecst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3562             : {
    3563         270 :         bit rep = TRUE;
    3564             : 
    3565         270 :         return STRbatSubstitutecst_imp(cntxt, mb, stk, pci, 5, &rep);
    3566             : }
    3567             : 
    3568             : static str
    3569           2 : STRbatReplace(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3570             : {
    3571             :         BATiter arg1i, arg2i, arg3i;
    3572             :         BAT *bn = NULL, *arg1 = NULL, *arg1s = NULL, *arg2 = NULL, *arg2s = NULL, *arg3 = NULL, *arg3s = NULL;
    3573             :         BUN q = 0;
    3574           2 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3575           2 :         str x, y, z, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3576             :         bool nils = false;
    3577           2 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0};
    3578             :         oid off1, off2, off3;
    3579           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    3580           2 :                 *s = getArgReference_bat(stk, pci, 2), *s2 = getArgReference_bat(stk, pci, 3),
    3581           2 :                 *sid1 = pci->argc == 7 ? getArgReference_bat(stk, pci, 4) : NULL,
    3582           2 :                 *sid2 = pci->argc == 7 ? getArgReference_bat(stk, pci, 5) : NULL,
    3583           2 :                 *sid3 = pci->argc == 7 ? getArgReference_bat(stk, pci, 6) : NULL;
    3584             : 
    3585             :         (void) cntxt;
    3586             :         (void) mb;
    3587           2 :         if (!buf) {
    3588           0 :                 msg = createException(MAL, "batstr.replace", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3589           0 :                 goto bailout;
    3590             :         }
    3591           2 :         if (!(arg1 = BATdescriptor(*l)) || !(arg2 = BATdescriptor(*s)) || !(arg3 = BATdescriptor(*s2))) {
    3592           0 :                 msg = createException(MAL, "batstr.replace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3593           0 :                 goto bailout;
    3594             :         }
    3595           2 :         if ((sid1 && !is_bat_nil(*sid1) && !(arg1s = BATdescriptor(*sid1))) ||
    3596           2 :                 (sid2 && !is_bat_nil(*sid2) && !(arg2s = BATdescriptor(*sid2))) || (sid3 && !is_bat_nil(*sid3) && !(arg3s = BATdescriptor(*sid3)))) {
    3597           0 :                 msg = createException(MAL, "batstr.replace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3598           0 :                 goto bailout;
    3599             :         }
    3600           2 :         q = canditer_init(&ci1, arg1, arg1s);
    3601           2 :         if (canditer_init(&ci2, arg2, arg2s) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, arg3, arg3s) != q || ci2.hseq != ci3.hseq) {
    3602           0 :                 msg = createException(MAL, "batstr.replace", ILLEGAL_ARGUMENT " Requires bats of identical size");
    3603           0 :                 goto bailout;
    3604             :         }
    3605           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3606           0 :                 msg = createException(MAL, "batstr.replace", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3607           0 :                 goto bailout;
    3608             :         }
    3609             : 
    3610           2 :         off1 = arg1->hseqbase;
    3611           2 :         off2 = arg2->hseqbase;
    3612           2 :         off3 = arg3->hseqbase;
    3613           2 :         arg1i = bat_iterator(arg1);
    3614           2 :         arg2i = bat_iterator(arg2);
    3615           2 :         arg3i = bat_iterator(arg3);
    3616           2 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense) {
    3617           6 :                 for (BUN i = 0; i < q; i++) {
    3618           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2), p3 = (canditer_next_dense(&ci3) - off3);
    3619           4 :                         x = (str) BUNtvar(arg1i, p1);
    3620           4 :                         y = (str) BUNtvar(arg2i, p2);
    3621           4 :                         z = (str) BUNtvar(arg3i, p3);
    3622             : 
    3623          12 :                         if (strNil(x) || strNil(y) || strNil(z)) {
    3624           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3625           0 :                                         msg = createException(MAL, "batstr.replace", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3626           0 :                                         goto bailout1;
    3627             :                                 }
    3628             :                                 nils = true;
    3629             :                         } else {
    3630           4 :                                 if ((msg = str_substitute(&buf, &buflen, x, y, z, TRUE)) != MAL_SUCCEED)
    3631           0 :                                         goto bailout1;
    3632           4 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3633           0 :                                         msg = createException(MAL, "batstr.replace", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3634           0 :                                         goto bailout1;
    3635             :                                 }
    3636             :                         }
    3637             :                 }
    3638             :         } else {
    3639           0 :                 for (BUN i = 0; i < q; i++) {
    3640           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2), p3 = (canditer_next(&ci3) - off3);
    3641           0 :                         x = (str) BUNtvar(arg1i, p1);
    3642           0 :                         y = (str) BUNtvar(arg2i, p2);
    3643           0 :                         z = (str) BUNtvar(arg3i, p3);
    3644             : 
    3645           0 :                         if (strNil(x) || strNil(y) || strNil(z)) {
    3646           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3647           0 :                                         msg = createException(MAL, "batstr.replace", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3648           0 :                                         goto bailout1;
    3649             :                                 }
    3650             :                                 nils = true;
    3651             :                         } else {
    3652           0 :                                 if ((msg = str_substitute(&buf, &buflen, x, y, z, TRUE)) != MAL_SUCCEED)
    3653           0 :                                         goto bailout1;
    3654           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3655           0 :                                         msg = createException(MAL, "batstr.replace", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3656           0 :                                         goto bailout1;
    3657             :                                 }
    3658             :                         }
    3659             :                 }
    3660             :         }
    3661           0 : bailout1:
    3662           2 :         bat_iterator_end(&arg1i);
    3663           2 :         bat_iterator_end(&arg2i);
    3664           2 :         bat_iterator_end(&arg3i);
    3665           2 : bailout:
    3666           2 :         GDKfree(buf);
    3667           2 :         finalize_ouput(res, bn, msg, nils, q);
    3668           2 :         unfix_inputs(6, arg1, arg1s, arg2, arg2s, arg3, arg3s);
    3669           2 :         return msg;
    3670             : }
    3671             : 
    3672             : static str
    3673           0 : STRbatInsert(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3674             : {
    3675             :         BATiter lefti, righti, starti, ncharsi;
    3676             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *start = NULL, *ss = NULL, *nchars = NULL, *ns = NULL, *right = NULL, *rs = NULL;
    3677             :         BUN q = 0;
    3678           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3679             :         int *sval, *lval, y, z;
    3680           0 :         str x, w, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3681             :         bool nils = false;
    3682           0 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0}, ci4 = {0};
    3683             :         oid off1, off2, off3, off4;
    3684           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    3685           0 :                 *s = getArgReference_bat(stk, pci, 2), *chars = getArgReference_bat(stk, pci, 3),
    3686           0 :                 *s2 = getArgReference_bat(stk, pci, 4),
    3687           0 :                 *sid1 = pci->argc == 9 ? getArgReference_bat(stk, pci, 5) : NULL,
    3688           0 :                 *sid2 = pci->argc == 9 ? getArgReference_bat(stk, pci, 6) : NULL,
    3689           0 :                 *sid3 = pci->argc == 9 ? getArgReference_bat(stk, pci, 7) : NULL,
    3690           0 :                 *sid4 = pci->argc == 9 ? getArgReference_bat(stk, pci, 8) : NULL;
    3691             : 
    3692             :         (void) cntxt;
    3693             :         (void) mb;
    3694           0 :         if (!buf) {
    3695           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3696           0 :                 goto bailout;
    3697             :         }
    3698           0 :         if (!(left = BATdescriptor(*l)) || !(start = BATdescriptor(*s)) || !(nchars = BATdescriptor(*chars)) || !(right = BATdescriptor(*s2))) {
    3699           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3700           0 :                 goto bailout;
    3701             :         }
    3702           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rs = BATdescriptor(*sid2))) ||
    3703           0 :                 (sid3 && !is_bat_nil(*sid3) && !(ss = BATdescriptor(*sid3))) || (sid4 && !is_bat_nil(*sid4) && !(ns = BATdescriptor(*sid4)))) {
    3704           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3705           0 :                 goto bailout;
    3706             :         }
    3707           0 :         q = canditer_init(&ci1, left, ls);
    3708           0 :         if (canditer_init(&ci2, start, ss) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, nchars, ns) != q ||
    3709           0 :                 ci2.hseq != ci3.hseq || canditer_init(&ci4, right, rs) != q || ci3.hseq != ci4.hseq) {
    3710           0 :                 msg = createException(MAL, "batstr.insert", ILLEGAL_ARGUMENT " Requires bats of identical size");
    3711           0 :                 goto bailout;
    3712             :         }
    3713           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3714           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3715           0 :                 goto bailout;
    3716             :         }
    3717             : 
    3718           0 :         off1 = left->hseqbase;
    3719           0 :         off2 = start->hseqbase;
    3720           0 :         off3 = nchars->hseqbase;
    3721           0 :         off4 = right->hseqbase;
    3722           0 :         lefti = bat_iterator(left);
    3723           0 :         starti = bat_iterator(start);
    3724           0 :         ncharsi = bat_iterator(nchars);
    3725           0 :         sval = starti.base;
    3726           0 :         lval = ncharsi.base;
    3727           0 :         righti = bat_iterator(right);
    3728           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense && ci4.tpe == cand_dense) {
    3729           0 :                 for (BUN i = 0; i < q; i++) {
    3730           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2),
    3731           0 :                                 p3 = (canditer_next_dense(&ci3) - off3), p4 = (canditer_next_dense(&ci4) - off4);
    3732           0 :                         x = (str) BUNtvar(lefti, p1);
    3733           0 :                         y = sval[p2];
    3734           0 :                         z = lval[p3];
    3735           0 :                         w = (str) BUNtvar(righti, p4);
    3736             : 
    3737           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z) || strNil(w)) {
    3738           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3739           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3740           0 :                                         goto bailout1;
    3741             :                                 }
    3742             :                                 nils = true;
    3743             :                         } else {
    3744           0 :                                 if ((msg = str_insert(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3745           0 :                                         goto bailout1;
    3746           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3747           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3748           0 :                                         goto bailout1;
    3749             :                                 }
    3750             :                         }
    3751             :                 }
    3752             :         } else {
    3753           0 :                 for (BUN i = 0; i < q; i++) {
    3754           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2),
    3755           0 :                                 p3 = (canditer_next(&ci3) - off3), p4 = (canditer_next(&ci4) - off4);
    3756           0 :                         x = (str) BUNtvar(lefti, p1);
    3757           0 :                         y = sval[p2];
    3758           0 :                         z = lval[p3];
    3759           0 :                         w = (str) BUNtvar(righti, p4);
    3760             : 
    3761           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z) || strNil(w)) {
    3762           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3763           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3764           0 :                                         goto bailout1;
    3765             :                                 }
    3766             :                                 nils = true;
    3767             :                         } else {
    3768           0 :                                 if ((msg = str_insert(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3769           0 :                                         goto bailout1;
    3770           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3771           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3772           0 :                                         goto bailout1;
    3773             :                                 }
    3774             :                         }
    3775             :                 }
    3776             :         }
    3777           0 : bailout1:
    3778           0 :         bat_iterator_end(&starti);
    3779           0 :         bat_iterator_end(&ncharsi);
    3780           0 :         bat_iterator_end(&lefti);
    3781           0 :         bat_iterator_end(&righti);
    3782           0 : bailout:
    3783           0 :         GDKfree(buf);
    3784           0 :         finalize_ouput(res, bn, msg, nils, q);
    3785           0 :         unfix_inputs(8, left, ls, start, ss, nchars, ns, right, rs);
    3786           0 :         return msg;
    3787             : }
    3788             : 
    3789             : static str
    3790           0 : STRbatInsertcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3791             : {
    3792             :         BATiter bi;
    3793             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    3794             :         BUN q = 0;
    3795           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3796           0 :         int y = *getArgReference_int(stk, pci, 2), z = *getArgReference_int(stk, pci, 3);
    3797           0 :         str x, w = *getArgReference_str(stk, pci, 4), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3798             :         bool nils = false;
    3799           0 :         struct canditer ci1 = {0};
    3800             :         oid off1;
    3801           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    3802           0 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    3803             : 
    3804             :         (void) cntxt;
    3805             :         (void) mb;
    3806           0 :         if (!buf) {
    3807           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3808           0 :                 goto bailout;
    3809             :         }
    3810           0 :         if (!(b = BATdescriptor(*bid))) {
    3811           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3812           0 :                 goto bailout;
    3813             :         }
    3814           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    3815           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3816           0 :                 goto bailout;
    3817             :         }
    3818           0 :         q = canditer_init(&ci1, b, bs);
    3819           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3820           0 :                 msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3821           0 :                 goto bailout;
    3822             :         }
    3823             : 
    3824           0 :         off1 = b->hseqbase;
    3825           0 :         bi = bat_iterator(b);
    3826           0 :         if (ci1.tpe == cand_dense) {
    3827           0 :                 for (BUN i = 0; i < q; i++) {
    3828           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    3829           0 :                         x = (str) BUNtvar(bi, p1);
    3830             : 
    3831           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z) || strNil(w)) {
    3832           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3833           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3834           0 :                                         goto bailout1;
    3835             :                                 }
    3836             :                                 nils = true;
    3837             :                         } else {
    3838           0 :                                 if ((msg = str_insert(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3839           0 :                                         goto bailout1;
    3840           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3841           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3842           0 :                                         goto bailout1;
    3843             :                                 }
    3844             :                         }
    3845             :                 }
    3846             :         } else {
    3847           0 :                 for (BUN i = 0; i < q; i++) {
    3848           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    3849           0 :                         x = (str) BUNtvar(bi, p1);
    3850             : 
    3851           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z) || strNil(w)) {
    3852           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3853           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3854           0 :                                         goto bailout1;
    3855             :                                 }
    3856             :                                 nils = true;
    3857             :                         } else {
    3858           0 :                                 if ((msg = str_insert(&buf, &buflen, x, y, z, w)) != MAL_SUCCEED)
    3859           0 :                                         goto bailout1;
    3860           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3861           0 :                                         msg = createException(MAL, "batstr.insert", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3862           0 :                                         goto bailout1;
    3863             :                                 }
    3864             :                         }
    3865             :                 }
    3866             :         }
    3867           0 : bailout1:
    3868           0 :         bat_iterator_end(&bi);
    3869           0 : bailout:
    3870           0 :         GDKfree(buf);
    3871           0 :         finalize_ouput(res, bn, msg, nils, q);
    3872           0 :         unfix_inputs(2, b, bs);
    3873           0 :         return msg;
    3874             : }
    3875             : 
    3876             : /*
    3877             :  * The substring functions require slightly different arguments
    3878             :  */
    3879             : static str
    3880         166 : STRbatsubstring_2nd_3rd_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3881             : {
    3882             :         BATiter bi;
    3883             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    3884             :         BUN q = 0;
    3885         166 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3886         166 :         int y = *getArgReference_int(stk, pci, 2), z = *getArgReference_int(stk, pci, 3);
    3887         166 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3888             :         bool nils = false;
    3889         166 :         struct canditer ci1 = {0};
    3890             :         oid off1;
    3891         166 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    3892         166 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    3893             : 
    3894             :         (void) cntxt;
    3895             :         (void) mb;
    3896         166 :         if (!buf) {
    3897           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3898           0 :                 goto bailout;
    3899             :         }
    3900         166 :         if (!(b = BATdescriptor(*bid))) {
    3901           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3902           0 :                 goto bailout;
    3903             :         }
    3904         166 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    3905           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3906           0 :                 goto bailout;
    3907             :         }
    3908         166 :         q = canditer_init(&ci1, b, bs);
    3909         166 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3910           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3911           0 :                 goto bailout;
    3912             :         }
    3913             : 
    3914         166 :         off1 = b->hseqbase;
    3915         166 :         bi = bat_iterator(b);
    3916         166 :         if (ci1.tpe == cand_dense) {
    3917     3739178 :                 for (BUN i = 0; i < q; i++) {
    3918     3739012 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    3919     3739012 :                         x = (str) BUNtvar(bi, p1);
    3920             : 
    3921     3739012 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    3922      152888 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3923           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3924           0 :                                         goto bailout1;
    3925             :                                 }
    3926             :                                 nils = true;
    3927             :                         } else {
    3928     3586124 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3929           0 :                                         goto bailout1;
    3930     3672069 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3931           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3932           0 :                                         goto bailout1;
    3933             :                                 }
    3934             :                         }
    3935             :                 }
    3936             :         } else {
    3937           0 :                 for (BUN i = 0; i < q; i++) {
    3938           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    3939           0 :                         x = (str) BUNtvar(bi, p1);
    3940             : 
    3941           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    3942           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    3943           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3944           0 :                                         goto bailout1;
    3945             :                                 }
    3946             :                                 nils = true;
    3947             :                         } else {
    3948           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    3949           0 :                                         goto bailout1;
    3950           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    3951           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3952           0 :                                         goto bailout1;
    3953             :                                 }
    3954             :                         }
    3955             :                 }
    3956             :         }
    3957           0 : bailout1:
    3958         166 :         bat_iterator_end(&bi);
    3959         166 : bailout:
    3960         166 :         GDKfree(buf);
    3961         166 :         finalize_ouput(res, bn, msg, nils, q);
    3962         166 :         unfix_inputs(2, b, bs);
    3963         166 :         return msg;
    3964             : }
    3965             : 
    3966             : static str
    3967           1 : STRbatsubstring_1st_2nd_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    3968             : {
    3969             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    3970             :         BUN q = 0;
    3971           1 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    3972           1 :         int y = *getArgReference_int(stk, pci, 2), z, *restrict input;
    3973           1 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    3974             :         bool nils = false;
    3975           1 :         struct canditer ci1 = {0};
    3976             :         oid off1;
    3977           1 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 3),
    3978           1 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    3979             :         BATiter bi;
    3980             : 
    3981             :         (void) cntxt;
    3982             :         (void) mb;
    3983           1 :         if (!buf) {
    3984           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3985           0 :                 goto bailout;
    3986             :         }
    3987           1 :         if (!(b = BATdescriptor(*bid))) {
    3988           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3989           0 :                 goto bailout;
    3990             :         }
    3991           1 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    3992           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    3993           0 :                 goto bailout;
    3994             :         }
    3995           1 :         q = canditer_init(&ci1, b, bs);
    3996           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    3997           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3998           0 :                 goto bailout;
    3999             :         }
    4000             : 
    4001           1 :         off1 = b->hseqbase;
    4002           1 :         bi = bat_iterator(b);
    4003           1 :         input = bi.base;
    4004           1 :         if (ci1.tpe == cand_dense) {
    4005           2 :                 for (BUN i = 0; i < q; i++) {
    4006           1 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    4007           1 :                         z = input[p1];
    4008             : 
    4009           1 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4010           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4011           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4012           0 :                                         goto bailout1;
    4013             :                                 }
    4014             :                                 nils = true;
    4015             :                         } else {
    4016           1 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4017           0 :                                         goto bailout1;
    4018           1 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4019           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4020           0 :                                         goto bailout1;
    4021             :                                 }
    4022             :                         }
    4023             :                 }
    4024             :         } else {
    4025           0 :                 for (BUN i = 0; i < q; i++) {
    4026           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    4027           0 :                         z = input[p1];
    4028             : 
    4029           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4030           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4031           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4032           0 :                                         goto bailout1;
    4033             :                                 }
    4034             :                                 nils = true;
    4035             :                         } else {
    4036           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4037           0 :                                         goto bailout1;
    4038           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4039           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4040           0 :                                         goto bailout1;
    4041             :                                 }
    4042             :                         }
    4043             :                 }
    4044             :         }
    4045           0 : bailout1:
    4046           1 :         bat_iterator_end(&bi);
    4047           1 : bailout:
    4048           1 :         GDKfree(buf);
    4049           1 :         finalize_ouput(res, bn, msg, nils, q);
    4050           1 :         unfix_inputs(2, b, bs);
    4051           1 :         return msg;
    4052             : }
    4053             : 
    4054             : static str
    4055           4 : STRbatsubstring_1st_3rd_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4056             : {
    4057             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    4058             :         BUN q = 0;
    4059           4 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4060           4 :         int y, z = *getArgReference_int(stk, pci, 3), *restrict input;
    4061           4 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    4062             :         bool nils = false;
    4063           4 :         struct canditer ci1 = {0};
    4064             :         oid off1;
    4065           4 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
    4066           4 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    4067             :         BATiter bi;
    4068             : 
    4069             :         (void) cntxt;
    4070             :         (void) mb;
    4071           4 :         if (!buf) {
    4072           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4073           0 :                 goto bailout;
    4074             :         }
    4075           4 :         if (!(b = BATdescriptor(*bid))) {
    4076           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4077           0 :                 goto bailout;
    4078             :         }
    4079           4 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    4080           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4081           0 :                 goto bailout;
    4082             :         }
    4083           4 :         q = canditer_init(&ci1, b, bs);
    4084           4 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    4085           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4086           0 :                 goto bailout;
    4087             :         }
    4088             : 
    4089           4 :         off1 = b->hseqbase;
    4090           4 :         bi = bat_iterator(b);
    4091           4 :         input = bi.base;
    4092           4 :         if (ci1.tpe == cand_dense) {
    4093           7 :                 for (BUN i = 0; i < q; i++) {
    4094           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    4095           4 :                         y = input[p1];
    4096             : 
    4097           4 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4098           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4099           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4100           0 :                                         goto bailout1;
    4101             :                                 }
    4102             :                                 nils = true;
    4103             :                         } else {
    4104           4 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4105           0 :                                         goto bailout1;
    4106           4 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4107           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4108           0 :                                         goto bailout1;
    4109             :                                 }
    4110             :                         }
    4111             :                 }
    4112             :         } else {
    4113           0 :                 for (BUN i = 0; i < q; i++) {
    4114           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    4115           0 :                         y = input[p1];
    4116             : 
    4117           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4118           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4119           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4120           0 :                                         goto bailout1;
    4121             :                                 }
    4122             :                                 nils = true;
    4123             :                         } else {
    4124           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4125           0 :                                         goto bailout1;
    4126           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4127           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4128           0 :                                         goto bailout1;
    4129             :                                 }
    4130             :                         }
    4131             :                 }
    4132             :         }
    4133           0 : bailout1:
    4134           3 :         bat_iterator_end(&bi);
    4135           4 : bailout:
    4136           4 :         GDKfree(buf);
    4137           4 :         finalize_ouput(res, bn, msg, nils, q);
    4138           4 :         unfix_inputs(2, b, bs);
    4139           4 :         return msg;
    4140             : }
    4141             : 
    4142             : static str
    4143           1 : STRbatsubstring_1st_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4144             : {
    4145             :         BAT *bn = NULL, *b = NULL, *bs = NULL, *lb = NULL, *lbs = NULL;
    4146             :         BUN q = 0;
    4147           1 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4148             :         int y, z, *vals1, *vals2;
    4149           1 :         str x = *getArgReference_str(stk, pci, 1), buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    4150             :         bool nils = false;
    4151           1 :         struct canditer ci1 = {0}, ci2 = {0};
    4152             :         oid off1, off2;
    4153           1 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
    4154           1 :                 *l = getArgReference_bat(stk, pci, 3),
    4155           1 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    4156           1 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    4157             :         BATiter bi;
    4158             :         BATiter lbi;
    4159             : 
    4160             :         (void) cntxt;
    4161             :         (void) mb;
    4162           1 :         if (!buf) {
    4163           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4164           0 :                 goto bailout;
    4165             :         }
    4166           1 :         if (!(b = BATdescriptor(*bid)) || !(lb = BATdescriptor(*l))) {
    4167           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4168           0 :                 goto bailout;
    4169             :         }
    4170           1 :         if ((sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(lbs = BATdescriptor(*sid2)))) {
    4171           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4172           0 :                 goto bailout;
    4173             :         }
    4174           1 :         q = canditer_init(&ci1, b, bs);
    4175           1 :         if (canditer_init(&ci2, lb, lbs) != q || ci1.hseq != ci2.hseq) {
    4176           0 :                 msg = createException(MAL, "batstr.substring", ILLEGAL_ARGUMENT " Requires bats of identical size");
    4177           0 :                 goto bailout;
    4178             :         }
    4179           1 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    4180           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4181           0 :                 goto bailout;
    4182             :         }
    4183             : 
    4184           1 :         off1 = b->hseqbase;
    4185           1 :         off2 = lb->hseqbase;
    4186           1 :         bi = bat_iterator(b);
    4187           1 :         lbi = bat_iterator(lb);
    4188           1 :         vals1 = bi.base;
    4189           1 :         vals2 = lbi.base;
    4190           1 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    4191           9 :                 for (BUN i = 0; i < q; i++) {
    4192           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    4193           8 :                         y = vals1[p1];
    4194           8 :                         z = vals2[p2];
    4195             : 
    4196           8 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4197           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4198           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4199           0 :                                         goto bailout1;
    4200             :                                 }
    4201             :                                 nils = true;
    4202             :                         } else {
    4203           8 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4204           0 :                                         goto bailout1;
    4205           8 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4206           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4207           0 :                                         goto bailout1;
    4208             :                                 }
    4209             :                         }
    4210             :                 }
    4211             :         } else {
    4212           0 :                 for (BUN i = 0; i < q; i++) {
    4213           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    4214           0 :                         y = vals1[p1];
    4215           0 :                         z = vals2[p2];
    4216             : 
    4217           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4218           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4219           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4220           0 :                                         goto bailout1;
    4221             :                                 }
    4222             :                                 nils = true;
    4223             :                         } else {
    4224           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4225           0 :                                         goto bailout1;
    4226           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4227           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4228           0 :                                         goto bailout1;
    4229             :                                 }
    4230             :                         }
    4231             :                 }
    4232             :         }
    4233           0 : bailout1:
    4234           1 :         bat_iterator_end(&bi);
    4235           1 :         bat_iterator_end(&lbi);
    4236           1 : bailout:
    4237           1 :         GDKfree(buf);
    4238           1 :         finalize_ouput(res, bn, msg, nils, q);
    4239           1 :         unfix_inputs(4, b, bs, lb, lbs);
    4240           1 :         return msg;
    4241             : }
    4242             : 
    4243             : static str
    4244          16 : STRbatsubstring_2nd_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4245             : {
    4246             :         BATiter bi;
    4247             :         BATiter lbi;
    4248             :         BAT *bn = NULL, *b = NULL, *bs = NULL, *lb = NULL, *lbs = NULL;
    4249             :         BUN q = 0;
    4250          16 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4251          16 :         int y = *getArgReference_int(stk, pci, 2), *len, z;
    4252          16 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    4253             :         bool nils = false;
    4254          16 :         struct canditer ci1 = {0}, ci2 = {0};
    4255             :         oid off1, off2;
    4256          16 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    4257          16 :                 *l = getArgReference_bat(stk, pci, 3),
    4258          16 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    4259          16 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    4260             : 
    4261             :         (void) cntxt;
    4262             :         (void) mb;
    4263          16 :         if (!buf) {
    4264           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4265           0 :                 goto bailout;
    4266             :         }
    4267          16 :         if (!(b = BATdescriptor(*bid)) || !(lb = BATdescriptor(*l))) {
    4268           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4269           0 :                 goto bailout;
    4270             :         }
    4271          16 :         if ((sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(lbs = BATdescriptor(*sid2)))) {
    4272           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4273           0 :                 goto bailout;
    4274             :         }
    4275          16 :         q = canditer_init(&ci1, b, bs);
    4276          16 :         if (canditer_init(&ci2, lb, lbs) != q || ci1.hseq != ci2.hseq) {
    4277           0 :                 msg = createException(MAL, "batstr.substring", ILLEGAL_ARGUMENT " Requires bats of identical size");
    4278           0 :                 goto bailout;
    4279             :         }
    4280          16 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    4281           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4282           0 :                 goto bailout;
    4283             :         }
    4284             : 
    4285          16 :         off1 = b->hseqbase;
    4286          16 :         off2 = lb->hseqbase;
    4287          16 :         bi = bat_iterator(b);
    4288          16 :         lbi = bat_iterator(lb);
    4289          16 :         len = lbi.base;
    4290          16 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    4291          20 :                 for (BUN i = 0; i < q; i++) {
    4292           4 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    4293           4 :                         x = (str) BUNtvar(bi, p1);
    4294           4 :                         z = len[p2];
    4295             : 
    4296           4 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4297           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4298           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4299           0 :                                         goto bailout1;
    4300             :                                 }
    4301             :                                 nils = true;
    4302             :                         } else {
    4303           4 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4304           0 :                                         goto bailout1;
    4305           4 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4306           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4307           0 :                                         goto bailout1;
    4308             :                                 }
    4309             :                         }
    4310             :                 }
    4311             :         } else {
    4312           0 :                 for (BUN i = 0; i < q; i++) {
    4313           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    4314           0 :                         x = (str) BUNtvar(bi, p1);
    4315           0 :                         z = len[p2];
    4316             : 
    4317           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4318           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4319           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4320           0 :                                         goto bailout1;
    4321             :                                 }
    4322             :                                 nils = true;
    4323             :                         } else {
    4324           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4325           0 :                                         goto bailout1;
    4326           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4327           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4328           0 :                                         goto bailout1;
    4329             :                                 }
    4330             :                         }
    4331             :                 }
    4332             :         }
    4333           0 : bailout1:
    4334          16 :         bat_iterator_end(&lbi);
    4335          16 :         bat_iterator_end(&bi);
    4336          16 : bailout:
    4337          16 :         GDKfree(buf);
    4338          16 :         finalize_ouput(res, bn, msg, nils, q);
    4339          16 :         unfix_inputs(4, b, bs, lb, lbs);
    4340          16 :         return msg;
    4341             : }
    4342             : 
    4343             : static str
    4344           0 : STRbatsubstring_3rd_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4345             : {
    4346             :         BATiter bi, lbi;
    4347             :         BAT *bn = NULL, *b = NULL, *bs = NULL, *lb = NULL, *lbs = NULL;
    4348             :         BUN q = 0;
    4349           0 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4350           0 :         int *start, y, z = *getArgReference_int(stk, pci, 3);
    4351           0 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    4352             :         bool nils = false;
    4353           0 :         struct canditer ci1 = {0}, ci2 = {0};
    4354             :         oid off1, off2;
    4355           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
    4356           0 :                 *l = getArgReference_bat(stk, pci, 2),
    4357           0 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 4) : NULL,
    4358           0 :                 *sid2 = pci->argc == 6 ? getArgReference_bat(stk, pci, 5) : NULL;
    4359             : 
    4360             :         (void) cntxt;
    4361             :         (void) mb;
    4362           0 :         if (!buf) {
    4363           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4364           0 :                 goto bailout;
    4365             :         }
    4366           0 :         if (!(b = BATdescriptor(*bid)) || !(lb = BATdescriptor(*l))) {
    4367           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4368           0 :                 goto bailout;
    4369             :         }
    4370           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(lbs = BATdescriptor(*sid2)))) {
    4371           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4372           0 :                 goto bailout;
    4373             :         }
    4374           0 :         q = canditer_init(&ci1, b, bs);
    4375           0 :         if (canditer_init(&ci2, lb, lbs) != q || ci1.hseq != ci2.hseq) {
    4376           0 :                 msg = createException(MAL, "batstr.substring", ILLEGAL_ARGUMENT " Requires bats of identical size");
    4377           0 :                 goto bailout;
    4378             :         }
    4379           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    4380           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4381           0 :                 goto bailout;
    4382             :         }
    4383             : 
    4384           0 :         off1 = b->hseqbase;
    4385           0 :         off2 = lb->hseqbase;
    4386           0 :         bi = bat_iterator(b);
    4387           0 :         lbi = bat_iterator(lb);
    4388           0 :         start = lbi.base;
    4389           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    4390           0 :                 for (BUN i = 0; i < q; i++) {
    4391           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    4392           0 :                         x = (str) BUNtvar(bi, p1);
    4393           0 :                         y = start[p2];
    4394             : 
    4395           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4396           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4397           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4398           0 :                                         goto bailout1;
    4399             :                                 }
    4400             :                                 nils = true;
    4401             :                         } else {
    4402           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4403           0 :                                         goto bailout1;
    4404           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4405           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4406           0 :                                         goto bailout1;
    4407             :                                 }
    4408             :                         }
    4409             :                 }
    4410             :         } else {
    4411           0 :                 for (BUN i = 0; i < q; i++) {
    4412           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    4413           0 :                         x = (str) BUNtvar(bi, p1);
    4414           0 :                         y = start[p2];
    4415             : 
    4416           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4417           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4418           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4419           0 :                                         goto bailout1;
    4420             :                                 }
    4421             :                                 nils = true;
    4422             :                         } else {
    4423           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4424           0 :                                         goto bailout1;
    4425           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4426           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4427           0 :                                         goto bailout1;
    4428             :                                 }
    4429             :                         }
    4430             :                 }
    4431             :         }
    4432           0 : bailout1:
    4433           0 :         bat_iterator_end(&lbi);
    4434           0 :         bat_iterator_end(&bi);
    4435           0 : bailout:
    4436           0 :         GDKfree(buf);
    4437           0 :         finalize_ouput(res, bn, msg, nils, q);
    4438           0 :         unfix_inputs(4, b, bs, lb, lbs);
    4439           0 :         return msg;
    4440             : }
    4441             : 
    4442             : static str
    4443           9 : STRbatsubstring(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4444             : {
    4445             :         BATiter lefti, starti, lengthi;
    4446             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *start = NULL, *ss = NULL, *length = NULL, *lens = NULL;
    4447             :         BUN q = 0;
    4448           9 :         size_t buflen = INITIAL_STR_BUFFER_LENGTH;
    4449             :         int *svals, *lvals, y, z;
    4450           9 :         str x, buf = GDKmalloc(buflen), msg = MAL_SUCCEED;
    4451             :         bool nils = false;
    4452           9 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0};
    4453             :         oid off1, off2, off3;
    4454           9 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    4455           9 :                 *r = getArgReference_bat(stk, pci, 2), *t = getArgReference_bat(stk, pci, 3),
    4456           9 :                 *sid1 = pci->argc == 7 ? getArgReference_bat(stk, pci, 4) : NULL,
    4457           9 :                 *sid2 = pci->argc == 7 ? getArgReference_bat(stk, pci, 5) : NULL,
    4458           9 :                 *sid3 = pci->argc == 7 ? getArgReference_bat(stk, pci, 6) : NULL;
    4459             : 
    4460             :         (void) cntxt;
    4461             :         (void) mb;
    4462           9 :         if (!buf) {
    4463           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4464           0 :                 goto bailout;
    4465             :         }
    4466           9 :         if (!(left = BATdescriptor(*l)) || !(start = BATdescriptor(*r)) || !(length = BATdescriptor(*t))) {
    4467           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4468           0 :                 goto bailout;
    4469             :         }
    4470           9 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) ||
    4471           9 :                 (sid2 && !is_bat_nil(*sid2) && !(ss = BATdescriptor(*sid2))) || (sid3 && !is_bat_nil(*sid3) && !(lens = BATdescriptor(*sid3)))) {
    4472           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4473           0 :                 goto bailout;
    4474             :         }
    4475           9 :         q = canditer_init(&ci1, left, ls);
    4476           9 :         if (canditer_init(&ci2, start, ss) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, length, lens) != q || ci2.hseq != ci3.hseq) {
    4477           0 :                 msg = createException(MAL, "batstr.substring", ILLEGAL_ARGUMENT " Requires bats of identical size");
    4478           0 :                 goto bailout;
    4479             :         }
    4480           9 :         if (!(bn = COLnew(ci1.hseq, TYPE_str, q, TRANSIENT))) {
    4481           0 :                 msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4482           0 :                 goto bailout;
    4483             :         }
    4484             : 
    4485           9 :         off1 = left->hseqbase;
    4486           9 :         off2 = start->hseqbase;
    4487           9 :         off3 = length->hseqbase;
    4488           9 :         lefti = bat_iterator(left);
    4489           9 :         starti = bat_iterator(start);
    4490           9 :         lengthi = bat_iterator(length);
    4491           9 :         svals = starti.base;
    4492           9 :         lvals = lengthi.base;
    4493           9 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense) {
    4494          66 :                 for (BUN i = 0; i < q; i++) {
    4495          57 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2), p3 = (canditer_next_dense(&ci3) - off3);
    4496          57 :                         x = (str) BUNtvar(lefti, p1);
    4497          57 :                         y = svals[p2];
    4498          57 :                         z = lvals[p3];
    4499             : 
    4500          57 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4501          48 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4502           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4503           0 :                                         goto bailout1;
    4504             :                                 }
    4505             :                                 nils = true;
    4506             :                         } else {
    4507           9 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4508           0 :                                         goto bailout1;
    4509           9 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4510           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4511           0 :                                         goto bailout1;
    4512             :                                 }
    4513             :                         }
    4514             :                 }
    4515             :         } else {
    4516           0 :                 for (BUN i = 0; i < q; i++) {
    4517           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2), p3 = (canditer_next(&ci3) - off3);
    4518           0 :                         x = (str) BUNtvar(lefti, p1);
    4519           0 :                         y = svals[p2];
    4520           0 :                         z = lvals[p3];
    4521             : 
    4522           0 :                         if (strNil(x) || is_int_nil(y) || is_int_nil(z)) {
    4523           0 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
    4524           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4525           0 :                                         goto bailout1;
    4526             :                                 }
    4527             :                                 nils = true;
    4528             :                         } else {
    4529           0 :                                 if ((msg = str_sub_string(&buf, &buflen, x, y, z)) != MAL_SUCCEED)
    4530           0 :                                         goto bailout1;
    4531           0 :                                 if (tfastins_nocheckVAR(bn, i, buf) != GDK_SUCCEED) {
    4532           0 :                                         msg = createException(MAL, "batstr.substring", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4533           0 :                                         goto bailout1;
    4534             :                                 }
    4535             :                         }
    4536             :                 }
    4537             :         }
    4538           0 : bailout1:
    4539           9 :         bat_iterator_end(&lefti);
    4540           9 :         bat_iterator_end(&starti);
    4541           9 :         bat_iterator_end(&lengthi);
    4542           9 : bailout:
    4543           9 :         GDKfree(buf);
    4544           9 :         finalize_ouput(res, bn, msg, nils, q);
    4545           9 :         unfix_inputs(6, left, ls, start, ss, length, lens);
    4546           9 :         return msg;
    4547             : }
    4548             : 
    4549             : static str
    4550           0 : STRbatstrLocatecst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4551             : {
    4552             :         BATiter bi;
    4553             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    4554             :         BUN q = 0;
    4555             :         int *restrict vals;
    4556           0 :         str x, y = *getArgReference_str(stk, pci, 2), msg = MAL_SUCCEED;
    4557             :         bool nils = false;
    4558           0 :         struct canditer ci1 = {0};
    4559             :         oid off1;
    4560           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    4561           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    4562             : 
    4563             :         (void) cntxt;
    4564             :         (void) mb;
    4565           0 :         if (!(b = BATdescriptor(*l))) {
    4566           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4567           0 :                 goto bailout;
    4568             :         }
    4569           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    4570           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4571           0 :                 goto bailout;
    4572             :         }
    4573           0 :         q = canditer_init(&ci1, b, bs);
    4574           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    4575           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4576           0 :                 goto bailout;
    4577             :         }
    4578             : 
    4579           0 :         off1 = b->hseqbase;
    4580           0 :         bi = bat_iterator(b);
    4581           0 :         vals = Tloc(bn, 0);
    4582           0 :         if (ci1.tpe == cand_dense) {
    4583           0 :                 for (BUN i = 0; i < q; i++) {
    4584           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    4585           0 :                         x = (str) BUNtvar(bi, p1);
    4586             : 
    4587           0 :                         if (strNil(x) || strNil(y)) {
    4588           0 :                                 vals[i] = int_nil;
    4589           0 :                                 nils = true;
    4590             :                         } else {
    4591           0 :                                 vals[i] = str_locate2(x, y, 1);
    4592             :                         }
    4593             :                 }
    4594             :         } else {
    4595           0 :                 for (BUN i = 0; i < q; i++) {
    4596           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    4597           0 :                         x = (str) BUNtvar(bi, p1);
    4598             : 
    4599           0 :                         if (strNil(x) || strNil(y)) {
    4600           0 :                                 vals[i] = int_nil;
    4601           0 :                                 nils = true;
    4602             :                         } else {
    4603           0 :                                 vals[i] = str_locate2(x, y, 1);
    4604             :                         }
    4605             :                 }
    4606             :         }
    4607           0 :         bat_iterator_end(&bi);
    4608           0 : bailout:
    4609           0 :         finalize_ouput(res, bn, msg, nils, q);
    4610           0 :         unfix_inputs(2, b, bs);
    4611           0 :         return msg;
    4612             : }
    4613             : 
    4614             : static str
    4615          24 : STRbatstrLocate_strcst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4616             : {
    4617             :         BATiter bi;
    4618             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    4619             :         BUN q = 0;
    4620             :         int *restrict vals;
    4621          24 :         str x = *getArgReference_str(stk, pci, 1), y, msg = MAL_SUCCEED;
    4622             :         bool nils = false;
    4623          24 :         struct canditer ci1 = {0};
    4624             :         oid off1;
    4625          24 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 2),
    4626          24 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
    4627             : 
    4628             :         (void) cntxt;
    4629             :         (void) mb;
    4630          24 :         if (!(b = BATdescriptor(*l))) {
    4631           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4632           0 :                 goto bailout;
    4633             :         }
    4634          24 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    4635           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4636           0 :                 goto bailout;
    4637             :         }
    4638          24 :         q = canditer_init(&ci1, b, bs);
    4639          24 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    4640           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4641           0 :                 goto bailout;
    4642             :         }
    4643             : 
    4644          24 :         off1 = b->hseqbase;
    4645          24 :         bi = bat_iterator(b);
    4646          24 :         vals = Tloc(bn, 0);
    4647          24 :         if (ci1.tpe == cand_dense) {
    4648          31 :                 for (BUN i = 0; i < q; i++) {
    4649           7 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    4650           7 :                         y = (str) BUNtvar(bi, p1);
    4651             : 
    4652          14 :                         if (strNil(x) || strNil(y)) {
    4653           0 :                                 vals[i] = int_nil;
    4654           0 :                                 nils = true;
    4655             :                         } else {
    4656           7 :                                 vals[i] = str_locate2(x, y, 1);
    4657             :                         }
    4658             :                 }
    4659             :         } else {
    4660           0 :                 for (BUN i = 0; i < q; i++) {
    4661           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    4662           0 :                         y = (str) BUNtvar(bi, p1);
    4663             : 
    4664           0 :                         if (strNil(x) || strNil(y)) {
    4665           0 :                                 vals[i] = int_nil;
    4666           0 :                                 nils = true;
    4667             :                         } else {
    4668           0 :                                 vals[i] = str_locate2(x, y, 1);
    4669             :                         }
    4670             :                 }
    4671             :         }
    4672          24 :         bat_iterator_end(&bi);
    4673          24 : bailout:
    4674          24 :         finalize_ouput(res, bn, msg, nils, q);
    4675          24 :         unfix_inputs(2, b, bs);
    4676          24 :         return msg;
    4677             : }
    4678             : 
    4679             : static str
    4680           2 : STRbatstrLocate(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4681             : {
    4682             :         BATiter lefti, righti;
    4683             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *right = NULL, *rs = NULL;
    4684             :         BUN q = 0;
    4685             :         int *restrict vals;
    4686             :         str x, y, msg = MAL_SUCCEED;
    4687             :         bool nils = false;
    4688           2 :         struct canditer ci1 = {0}, ci2 = {0};
    4689             :         oid off1, off2;
    4690           2 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    4691           2 :                 *r = getArgReference_bat(stk, pci, 2),
    4692           2 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
    4693           2 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    4694             : 
    4695             :         (void) cntxt;
    4696             :         (void) mb;
    4697           2 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
    4698           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4699           0 :                 goto bailout;
    4700             :         }
    4701           2 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) ||
    4702           2 :                 (sid2 && !is_bat_nil(*sid2) && !(rs = BATdescriptor(*sid2)))) {
    4703           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4704           0 :                 goto bailout;
    4705             :         }
    4706           2 :         q = canditer_init(&ci1, left, ls);
    4707           2 :         if (canditer_init(&ci2, right, rs) != q || ci1.hseq != ci2.hseq) {
    4708           0 :                 msg = createException(MAL, "batstr.locate", ILLEGAL_ARGUMENT " Requires bats of identical size");
    4709           0 :                 goto bailout;
    4710             :         }
    4711           2 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    4712           0 :                 msg = createException(MAL, "batstr.locate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4713           0 :                 goto bailout;
    4714             :         }
    4715             : 
    4716           2 :         off1 = left->hseqbase;
    4717           2 :         off2 = right->hseqbase;
    4718           2 :         lefti = bat_iterator(left);
    4719           2 :         righti = bat_iterator(right);
    4720           2 :         vals = Tloc(bn, 0);
    4721           2 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    4722          10 :                 for (BUN i = 0; i < q; i++) {
    4723           8 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
    4724           8 :                         x = (str) BUNtvar(lefti, p1);
    4725           8 :                         y = (str) BUNtvar(righti, p2);
    4726             : 
    4727          16 :                         if (strNil(x) || strNil(y)) {
    4728           0 :                                 vals[i] = int_nil;
    4729           0 :                                 nils = true;
    4730             :                         } else {
    4731           8 :                                 vals[i] = str_locate2(x, y, 1);
    4732             :                         }
    4733             :                 }
    4734             :         } else {
    4735           0 :                 for (BUN i = 0; i < q; i++) {
    4736           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
    4737           0 :                         x = (str) BUNtvar(lefti, p1);
    4738           0 :                         y = (str) BUNtvar(righti, p2);
    4739             : 
    4740           0 :                         if (strNil(x) || strNil(y)) {
    4741           0 :                                 vals[i] = int_nil;
    4742           0 :                                 nils = true;
    4743             :                         } else {
    4744           0 :                                 vals[i] = str_locate2(x, y, 1);
    4745             :                         }
    4746             :                 }
    4747             :         }
    4748           2 :         bat_iterator_end(&lefti);
    4749           2 :         bat_iterator_end(&righti);
    4750           2 : bailout:
    4751           2 :         finalize_ouput(res, bn, msg, nils, q);
    4752           2 :         unfix_inputs(4, left, ls, right, rs);
    4753           2 :         return msg;
    4754             : }
    4755             : 
    4756             : static str
    4757           0 : STRbatstrLocate3cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4758             : {
    4759             :         BATiter bi;
    4760             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
    4761             :         BUN q = 0;
    4762           0 :         int *restrict vals, z = *getArgReference_int(stk, pci, 3);
    4763           0 :         str x, y = *getArgReference_str(stk, pci, 2), msg = MAL_SUCCEED;
    4764             :         bool nils = false;
    4765           0 :         struct canditer ci1 = {0};
    4766             :         oid off1;
    4767           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    4768           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
    4769             : 
    4770             :         (void) cntxt;
    4771             :         (void) mb;
    4772           0 :         if (!(b = BATdescriptor(*l))) {
    4773           0 :                 msg = createException(MAL, "batstr.locate2", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4774           0 :                 goto bailout;
    4775             :         }
    4776           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
    4777           0 :                 msg = createException(MAL, "batstr.locate2", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4778           0 :                 goto bailout;
    4779             :         }
    4780           0 :         q = canditer_init(&ci1, b, bs);
    4781           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    4782           0 :                 msg = createException(MAL, "batstr.locate2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4783           0 :                 goto bailout;
    4784             :         }
    4785             : 
    4786           0 :         off1 = b->hseqbase;
    4787           0 :         bi = bat_iterator(b);
    4788           0 :         vals = Tloc(bn, 0);
    4789           0 :         if (ci1.tpe == cand_dense) {
    4790           0 :                 for (BUN i = 0; i < q; i++) {
    4791           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
    4792           0 :                         x = (str) BUNtvar(bi, p1);
    4793             : 
    4794           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    4795           0 :                                 vals[i] = int_nil;
    4796           0 :                                 nils = true;
    4797             :                         } else {
    4798           0 :                                 vals[i] = str_locate2(x, y, z);
    4799             :                         }
    4800             :                 }
    4801             :         } else {
    4802           0 :                 for (BUN i = 0; i < q; i++) {
    4803           0 :                         oid p1 = (canditer_next(&ci1) - off1);
    4804           0 :                         x = (str) BUNtvar(bi, p1);
    4805             : 
    4806           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    4807           0 :                                 vals[i] = int_nil;
    4808           0 :                                 nils = true;
    4809             :                         } else {
    4810           0 :                                 vals[i] = str_locate2(x, y, z);
    4811             :                         }
    4812             :                 }
    4813             :         }
    4814           0 :         bat_iterator_end(&bi);
    4815           0 : bailout:
    4816           0 :         finalize_ouput(res, bn, msg, nils, q);
    4817           0 :         unfix_inputs(2, b, bs);
    4818           0 :         return msg;
    4819             : }
    4820             : 
    4821             : static str
    4822           0 : STRbatstrLocate3(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    4823             : {
    4824             :         BATiter lefti, righti, starti;
    4825             :         BAT *bn = NULL, *left = NULL, *ls = NULL, *right = NULL, *rs = NULL, *start = NULL, *ss = NULL;
    4826             :         BUN q = 0;
    4827             :         int *restrict vals, *restrict svals, z;
    4828             :         str x, y, msg = MAL_SUCCEED;
    4829             :         bool nils = false;
    4830           0 :         struct canditer ci1 = {0}, ci2 = {0}, ci3 = {0};
    4831             :         oid off1, off2, off3;
    4832           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
    4833           0 :                 *r = getArgReference_bat(stk, pci, 2), *s = getArgReference_bat(stk, pci, 3),
    4834           0 :                 *sid1 = pci->argc == 7 ? getArgReference_bat(stk, pci, 4) : NULL,
    4835           0 :                 *sid2 = pci->argc == 7 ? getArgReference_bat(stk, pci, 5) : NULL,
    4836           0 :                 *sid3 = pci->argc == 7 ? getArgReference_bat(stk, pci, 6) : NULL;
    4837             : 
    4838             :         (void) cntxt;
    4839             :         (void) mb;
    4840           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r)) || !(start = BATdescriptor(*s))) {
    4841           0 :                 msg = createException(MAL, "batstr.locate2", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4842           0 :                 goto bailout;
    4843             :         }
    4844           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(ls = BATdescriptor(*sid1))) ||
    4845           0 :                 (sid2 && !is_bat_nil(*sid2) && !(rs = BATdescriptor(*sid2))) || (sid3 && !is_bat_nil(*sid3) && !(ss = BATdescriptor(*sid3)))) {
    4846           0 :                 msg = createException(MAL, "batstr.locate2", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    4847           0 :                 goto bailout;
    4848             :         }
    4849           0 :         q = canditer_init(&ci1, left, ls);
    4850           0 :         if (canditer_init(&ci2, right, rs) != q || ci1.hseq != ci2.hseq || canditer_init(&ci3, start, ss) != q || ci2.hseq != ci3.hseq) {
    4851           0 :                 msg = createException(MAL, "batstr.locate2", ILLEGAL_ARGUMENT " Requires bats of identical size");
    4852           0 :                 goto bailout;
    4853             :         }
    4854           0 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, q, TRANSIENT))) {
    4855           0 :                 msg = createException(MAL, "batstr.locate2", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4856           0 :                 goto bailout;
    4857             :         }
    4858             : 
    4859           0 :         off1 = left->hseqbase;
    4860           0 :         off2 = right->hseqbase;
    4861           0 :         off3 = start->hseqbase;
    4862           0 :         lefti = bat_iterator(left);
    4863           0 :         righti = bat_iterator(right);
    4864           0 :         starti = bat_iterator(start);
    4865           0 :         svals = starti.base;
    4866           0 :         vals = Tloc(bn, 0);
    4867           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense && ci3.tpe == cand_dense) {
    4868           0 :                 for (BUN i = 0; i < q; i++) {
    4869           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2), p3 = (canditer_next_dense(&ci3) - off3);
    4870           0 :                         x = (str) BUNtvar(lefti, p1);
    4871           0 :                         y = (str) BUNtvar(righti, p2);
    4872           0 :                         z = svals[p3];
    4873             : 
    4874           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    4875           0 :                                 vals[i] = int_nil;
    4876           0 :                                 nils = true;
    4877             :                         } else {
    4878           0 :                                 vals[i] = str_locate2(x, y, z);
    4879             :                         }
    4880             :                 }
    4881             :         } else {
    4882           0 :                 for (BUN i = 0; i < q; i++) {
    4883           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2), p3 = (canditer_next(&ci3) - off3);
    4884           0 :                         x = (str) BUNtvar(lefti, p1);
    4885           0 :                         y = (str) BUNtvar(righti, p2);
    4886           0 :                         z = svals[p3];
    4887             : 
    4888           0 :                         if (strNil(x) || strNil(y) || is_int_nil(z)) {
    4889           0 :                                 vals[i] = int_nil;
    4890           0 :                                 nils = true;
    4891             :                         } else {
    4892           0 :                                 vals[i] = str_locate2(x, y, z);
    4893             :                         }
    4894             :                 }
    4895             :         }
    4896           0 :         bat_iterator_end(&starti);
    4897           0 :         bat_iterator_end(&lefti);
    4898           0 :         bat_iterator_end(&righti);
    4899           0 : bailout:
    4900           0 :         finalize_ouput(res, bn, msg, nils, q);
    4901           0 :         unfix_inputs(6, left, ls, right, rs, start, ss);
    4902           0 :         return msg;
    4903             : }
    4904             : 
    4905             : #include "mel.h"
    4906             : mel_func batstr_init_funcs[] = {
    4907             :  pattern("batstr", "length", STRbatLength, false, "Return the length of a string.", args(1,2, batarg("",int),batarg("s",str))),
    4908             :  pattern("batstr", "length", STRbatLength, false, "Return the length of a string.", args(1,3, batarg("",int),batarg("s",str),batarg("s",oid))),
    4909             :  pattern("batstr", "nbytes", STRbatBytes, false, "Return the string length in bytes.", args(1,2, batarg("",int),batarg("s",str))),
    4910             :  pattern("batstr", "nbytes", STRbatBytes, false, "Return the string length in bytes.", args(1,3, batarg("",int),batarg("s",str),batarg("s",oid))),
    4911             :  pattern("batstr", "toLower", STRbatLower, false, "Convert a string to lower case.", args(1,2, batarg("",str),batarg("s",str))),
    4912             :  pattern("batstr", "toLower", STRbatLower, false, "Convert a string to lower case.", args(1,3, batarg("",str),batarg("s",str),batarg("s",oid))),
    4913             :  pattern("batstr", "toUpper", STRbatUpper, false, "Convert a string to upper case.", args(1,2, batarg("",str),batarg("s",str))),
    4914             :  pattern("batstr", "toUpper", STRbatUpper, false, "Convert a string to upper case.", args(1,3, batarg("",str),batarg("s",str),batarg("s",oid))),
    4915             :  pattern("batstr", "trim", STRbatStrip, false, "Strip whitespaces around a string.", args(1,2, batarg("",str),batarg("s",str))),
    4916             :  pattern("batstr", "trim", STRbatStrip, false, "Strip whitespaces around a string.", args(1,3, batarg("",str),batarg("s",str),batarg("s",oid))),
    4917             :  pattern("batstr", "ltrim", STRbatLtrim, false, "Strip whitespaces from start of a string.", args(1,2, batarg("",str),batarg("s",str))),
    4918             :  pattern("batstr", "ltrim", STRbatLtrim, false, "Strip whitespaces from start of a string.", args(1,3, batarg("",str),batarg("s",str),batarg("s",oid))),
    4919             :  pattern("batstr", "rtrim", STRbatRtrim, false, "Strip whitespaces from end of a string.", args(1,2, batarg("",str),batarg("s",str))),
    4920             :  pattern("batstr", "rtrim", STRbatRtrim, false, "Strip whitespaces from end of a string.", args(1,3, batarg("",str),batarg("s",str),batarg("s",oid))),
    4921             :  pattern("batstr", "trim2", STRbatStrip2_const, false, "Strip characters in the second string around the first strings.", args(1,3, batarg("",str),batarg("s",str),arg("s2",str))),
    4922             :  pattern("batstr", "trim2", STRbatStrip2_const, false, "Strip characters in the second string around the first strings.", args(1,4, batarg("",str),batarg("s",str),arg("s2",str),batarg("s",oid))),
    4923             :  pattern("batstr", "trim2", STRbatStrip2_1st_const, false, "Strip characters in the second string around the first strings.", args(1,3, batarg("",str),arg("s",str),batarg("s2",str))),
    4924             :  pattern("batstr", "trim2", STRbatStrip2_1st_const, false, "Strip characters in the second string around the first strings.", args(1,4, batarg("",str),arg("s",str),batarg("s2",str),batarg("s",oid))),
    4925             :  pattern("batstr", "ltrim2", STRbatLtrim2_const, false, "Strip characters in the second string from start of the first strings.", args(1,3, batarg("",str),batarg("s",str),arg("s2",str))),
    4926             :  pattern("batstr", "ltrim2", STRbatLtrim2_const, false, "Strip characters in the second string from start of the first strings.", args(1,4, batarg("",str),batarg("s",str),arg("s2",str),batarg("s",oid))),
    4927             :  pattern("batstr", "ltrim2", STRbatLtrim2_1st_const, false, "Strip characters in the second string from start of the first strings.", args(1,3, batarg("",str),arg("s",str),batarg("s2",str))),
    4928             :  pattern("batstr", "ltrim2", STRbatLtrim2_1st_const, false, "Strip characters in the second string from start of the first strings.", args(1,4, batarg("",str),arg("s",str),batarg("s2",str),batarg("s",oid))),
    4929             :  pattern("batstr", "rtrim2", STRbatRtrim2_const, false, "Strip characters in the second string from end of the first strings.", args(1,3, batarg("",str),batarg("s",str),arg("s2",str))),
    4930             :  pattern("batstr", "rtrim2", STRbatRtrim2_const, false, "Strip characters in the second string from end of the first strings.", args(1,4, batarg("",str),batarg("s",str),arg("s2",str),batarg("s",oid))),
    4931             :  pattern("batstr", "rtrim2", STRbatRtrim2_1st_const, false, "Strip characters in the second string from end of the first strings.", args(1,3, batarg("",str),arg("s",str),batarg("s2",str))),
    4932             :  pattern("batstr", "rtrim2", STRbatRtrim2_1st_const, false, "Strip characters in the second string from end of the first strings.", args(1,4, batarg("",str),arg("s",str),batarg("s2",str),batarg("s",oid))),
    4933             :  pattern("batstr", "trim2", STRbatStrip2_bat, false, "Strip characters in the second strings around the first strings.", args(1,3, batarg("",str),batarg("s",str),batarg("s2",str))),
    4934             :  pattern("batstr", "trim2", STRbatStrip2_bat, false, "Strip characters in the second strings around the first strings.", args(1,5, batarg("",str),batarg("s",str),batarg("s2",str),batarg("s1",oid),batarg("s2",oid))),
    4935             :  pattern("batstr", "ltrim2", STRbatLtrim2_bat, false, "Strip characters in the second strings from start of the first strings.", args(1,3, batarg("",str),batarg("s",str),batarg("s2",str))),
    4936             :  pattern("batstr", "ltrim2", STRbatLtrim2_bat, false, "Strip characters in the second strings from start of the first strings.", args(1,5, batarg("",str),batarg("s",str),batarg("s2",str),batarg("s1",oid),batarg("s2",oid))),
    4937             :  pattern("batstr", "rtrim2", STRbatRtrim2_bat, false, "Strip characters in the second strings from end of the first strings.", args(1,3, batarg("",str),batarg("s",str),batarg("s2",str))),
    4938             :  pattern("batstr", "rtrim2", STRbatRtrim2_bat, false, "Strip characters in the second strings from end of the first strings.", args(1,5, batarg("",str),batarg("s",str),batarg("s2",str),batarg("s1",oid),batarg("s2",oid))),
    4939             :  pattern("batstr", "lpad", STRbatLpad_const, false, "Prepend whitespaces to the strings to reach the given length. Truncate the strings on the right if their lengths is larger than the given length.", args(1,3, batarg("",str),batarg("s",str),arg("n",int))),
    4940             :  pattern("batstr", "lpad", STRbatLpad_const, false, "Prepend whitespaces to the strings to reach the given length. Truncate the strings on the right if their lengths is larger than the given length.", args(1,4, batarg("",str),batarg("s",str),arg("n",int),batarg("s",oid))),
    4941             :  pattern("batstr", "rpad", STRbatRpad_const, false, "Append whitespaces to the strings to reach the given length. Truncate the strings on the right if their lengths is larger than the given length.", args(1,3, batarg("",str),batarg("s",str),arg("n",int))),
    4942             :  pattern("batstr", "rpad", STRbatRpad_const, false, "Append whitespaces to the strings to reach the given length. Truncate the strings on the right if their lengths is larger than the given length.", args(1,4, batarg("",str),batarg("s",str),arg("n",int),batarg("s",oid))),
    4943             :  pattern("batstr", "lpad", STRbatLpad_1st_const, false, "Prepend whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,3, batarg("",str),arg("s",str),batarg("n",int))),
    4944             :  pattern("batstr", "lpad", STRbatLpad_1st_const, false, "Prepend whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,4, batarg("",str),arg("s",str),batarg("n",int),batarg("s",oid))),
    4945             :  pattern("batstr", "rpad", STRbatRpad_1st_const, false, "Append whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,3, batarg("",str),arg("s",str),batarg("n",int))),
    4946             :  pattern("batstr", "rpad", STRbatRpad_1st_const, false, "Append whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,4, batarg("",str),arg("s",str),batarg("n",int),batarg("s",oid))),
    4947             :  pattern("batstr", "lpad", STRbatLpad_bat, false, "Prepend whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,3, batarg("",str),batarg("s",str),batarg("n",int))),
    4948             :  pattern("batstr", "lpad", STRbatLpad_bat, false, "Prepend whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,5, batarg("",str),batarg("s",str),batarg("n",int),batarg("s1",oid),batarg("s2",oid))),
    4949             :  pattern("batstr", "rpad", STRbatRpad_bat, false, "Append whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,3, batarg("",str),batarg("s",str),batarg("n",int))),
    4950             :  pattern("batstr", "rpad", STRbatRpad_bat, false, "Append whitespaces to the strings to reach the given lengths. Truncate the strings on the right if their lengths is larger than the given lengths.", args(1,5, batarg("",str),batarg("s",str),batarg("n",int),batarg("s1",oid),batarg("s2",oid))),
    4951             :  pattern("batstr", "lpad3", STRbatLpad3_const_const, false, "Prepend the second string to the first strings to reach the given length. Truncate the first strings on the right if their lengths is larger than the given length.", args(1,4, batarg("",str),batarg("s",str),arg("n",int),arg("s2",str))),
    4952             :  pattern("batstr", "rpad3", STRbatRpad3_const_const, false, "Append the second string to the first strings to reach the given length. Truncate the first strings on the right if their lengths is larger than the given length.", args(1,4, batarg("",str),batarg("s",str),arg("n",int),arg("s2",str))),
    4953             :  pattern("batstr", "lpad3", STRbatLpad3_bat_const, false, "Prepend the second string to the first strings to reach the given lengths. Truncate the first strings on the right if their lengths is larger than the given lengths.", args(1,4, batarg("",str),batarg("s",str),batarg("n",int),arg("s2",str))),
    4954             :  pattern("batstr", "rpad3", STRbatRpad3_bat_const, false, "Append the second string to the first strings to reach the given lengths. Truncate the first strings on the right if their lengths is larger than the given lengths.", args(1,4, batarg("",str),batarg("s",str),batarg("n",int),arg("s2",str))),
    4955             :  pattern("batstr", "lpad3", STRbatLpad3_const_bat, false, "Prepend the second strings to the first strings to reach the given length. Truncate the first strings on the right if their lengths is larger than the given length.", args(1,4, batarg("",str),batarg("s",str),arg("n",int),batarg("s2",str))),
    4956             :  pattern("batstr", "rpad3", STRbatRpad3_const_bat, false, "Append the second strings to the first strings to reach the given length. Truncate the first strings on the right if their lengths is larger than the given length.", args(1,4, batarg("",str),batarg("s",str),arg("n",int),batarg("s2",str))),
    4957             :  pattern("batstr", "lpad3", STRbatLpad3_bat_bat, false, "Prepend the second strings to the first strings to reach the given lengths. Truncate the first strings on the right if their lengths is larger than the given lengths.", args(1,4, batarg("",str),batarg("s",str),batarg("n",int),batarg("s2",str))),
    4958             :  pattern("batstr", "rpad3", STRbatRpad3_bat_bat, false, "Append the second strings to the first strings to reach the given lengths. Truncate the first strings on the right if their lengths is larger than the given lengths.", args(1,4, batarg("",str),batarg("s",str),batarg("n",int),batarg("s2",str))),
    4959             :  pattern("batstr", "startsWith", STRbatPrefix, false, "Prefix check.", args(1,3, batarg("",bit),batarg("s",str),batarg("prefix",str))),
    4960             :  pattern("batstr", "startsWith", STRbatPrefix, false, "Prefix check.", args(1,5, batarg("",bit),batarg("s",str),batarg("prefix",str),batarg("s1",oid),batarg("s2",oid))),
    4961             :  pattern("batstr", "startsWith", STRbatPrefixcst, false, "Prefix check.", args(1,3, batarg("",bit),batarg("s",str),arg("prefix",str))),
    4962             :  pattern("batstr", "startsWith", STRbatPrefixcst, false, "Prefix check.", args(1,4, batarg("",bit),batarg("s",str),arg("prefix",str),batarg("s",oid))),
    4963             :  pattern("batstr", "startsWith", STRbatPrefix_strcst, false, "Prefix check.", args(1,3, batarg("",bit),arg("s",str),batarg("prefix",str))),
    4964             :  pattern("batstr", "startsWith", STRbatPrefix_strcst, false, "Prefix check.", args(1,4, batarg("",bit),arg("s",str),batarg("prefix",str),batarg("s",oid))),
    4965             :  pattern("batstr", "endsWith", STRbatSuffix, false, "Suffix check.", args(1,3, batarg("",bit),batarg("s",str),batarg("suffix",str))),
    4966             :  pattern("batstr", "endsWith", STRbatSuffix, false, "Suffix check.", args(1,5, batarg("",bit),batarg("s",str),batarg("suffix",str),batarg("s1",oid),batarg("s2",oid))),
    4967             :  pattern("batstr", "endsWith", STRbatSuffixcst, false, "Suffix check.", args(1,3, batarg("",bit),batarg("s",str),arg("suffix",str))),
    4968             :  pattern("batstr", "endsWith", STRbatSuffixcst, false, "Suffix check.", args(1,4, batarg("",bit),batarg("s",str),arg("suffix",str),batarg("s",oid))),
    4969             :  pattern("batstr", "endsWith", STRbatSuffix_strcst, false, "Suffix check.", args(1,3, batarg("",bit),arg("s",str),batarg("suffix",str))),
    4970             :  pattern("batstr", "endsWith", STRbatSuffix_strcst, false, "Suffix check.", args(1,4, batarg("",bit),arg("s",str),batarg("suffix",str),batarg("s",oid))),
    4971             :  pattern("batstr", "splitpart", STRbatsplitpart, false, "Split string on delimiter. Returns\ngiven field (counting from one.)", args(1,4, batarg("",str),batarg("s",str),batarg("needle",str),batarg("field",int))),
    4972             :  pattern("batstr", "splitpart", STRbatsplitpartcst, false, "Split string on delimiter. Returns\ngiven field (counting from one.)", args(1,4, batarg("",str),batarg("s",str),arg("needle",str),arg("field",int))),
    4973             :  pattern("batstr", "splitpart", STRbatsplitpart_needlecst, false, "Split string on delimiter. Returns\ngiven field (counting from one.)", args(1,4, batarg("",str),batarg("s",str),arg("needle",str),batarg("field",int))),
    4974             :  pattern("batstr", "splitpart", STRbatsplitpart_fieldcst, false, "Split string on delimiter. Returns\ngiven field (counting from one.)", args(1,4, batarg("",str),batarg("s",str),batarg("needle",str),arg("field",int))),
    4975             :  pattern("batstr", "search", STRbatstrSearch, false, "Search for a substring. Returns position, -1 if not found.", args(1,3, batarg("",int),batarg("s",str),batarg("c",str))),
    4976             :  pattern("batstr", "search", STRbatstrSearch, false, "Search for a substring. Returns position, -1 if not found.", args(1,5, batarg("",int),batarg("s",str),batarg("c",str),batarg("s1",oid),batarg("s2",oid))),
    4977             :  pattern("batstr", "search", STRbatstrSearchcst, false, "Search for a substring. Returns position, -1 if not found.", args(1,3, batarg("",int),batarg("s",str),arg("c",str))),
    4978             :  pattern("batstr", "search", STRbatstrSearchcst, false, "Search for a substring. Returns position, -1 if not found.", args(1,4, batarg("",int),batarg("s",str),arg("c",str),batarg("s",oid))),
    4979             :  pattern("batstr", "search", STRbatstrSearch_strcst, false, "Search for a substring. Returns position, -1 if not found.", args(1,3, batarg("",int),arg("s",str),batarg("c",str))),
    4980             :  pattern("batstr", "search", STRbatstrSearch_strcst, false, "Search for a substring. Returns position, -1 if not found.", args(1,4, batarg("",int),arg("s",str),batarg("c",str),batarg("s",oid))),
    4981             :  pattern("batstr", "r_search", STRbatRstrSearch, false, "Reverse search for a substring. Returns position, -1 if not found.", args(1,3, batarg("",int),batarg("s",str),batarg("c",str))),
    4982             :  pattern("batstr", "r_search", STRbatRstrSearch, false, "Reverse search for a substring. Returns position, -1 if not found.", args(1,5, batarg("",int),batarg("s",str),batarg("c",str),batarg("s1",oid),batarg("s2",oid))),
    4983             :  pattern("batstr", "r_search", STRbatRstrSearchcst, false, "Reverse search for a substring. Returns position, -1 if not found.", args(1,3, batarg("",int),batarg("s",str),arg("c",str))),
    4984             :  pattern("batstr", "r_search", STRbatRstrSearchcst, false, "Reverse search for a substring. Returns position, -1 if not found.", args(1,4, batarg("",int),batarg("s",str),arg("c",str),batarg("s",oid))),
    4985             :  pattern("batstr", "r_search", STRbatRstrSearch_strcst, false, "Reverse search for a substring. Returns position, -1 if not found.", args(1,3, batarg("",int),arg("s",str),batarg("c",str))),
    4986             :  pattern("batstr", "r_search", STRbatRstrSearch_strcst, false, "Reverse search for a substring. Returns position, -1 if not found.", args(1,4, batarg("",int),arg("s",str),batarg("c",str),batarg("s",oid))),
    4987             :  pattern("batstr", "string", STRbatTail, false, "Return the tail s[offset..n] of a string s[0..n].", args(1,3, batarg("",str),batarg("b",str),batarg("offset",int))),
    4988             :  pattern("batstr", "string", STRbatTail, false, "Return the tail s[offset..n] of a string s[0..n].", args(1,5, batarg("",str),batarg("b",str),batarg("offset",int),batarg("s1",oid),batarg("s2",oid))),
    4989             :  pattern("batstr", "string", STRbatTailcst, false, "Return the tail s[offset..n] of a string s[0..n].", args(1,3, batarg("",str),batarg("b",str),arg("offset",int))),
    4990             :  pattern("batstr", "string", STRbatTailcst, false, "Return the tail s[offset..n] of a string s[0..n].", args(1,4, batarg("",str),batarg("b",str),arg("offset",int),batarg("s",oid))),
    4991             :  pattern("batstr", "string", STRbatTail_strcst, false, "Return the tail s[offset..n] of a string s[0..n].", args(1,3, batarg("",str),arg("b",str),batarg("offset",int))),
    4992             :  pattern("batstr", "string", STRbatTail_strcst, false, "Return the tail s[offset..n] of a string s[0..n].", args(1,4, batarg("",str),arg("b",str),batarg("offset",int),batarg("s",oid))),
    4993             :  pattern("batstr", "ascii", STRbatAscii, false, "Return unicode of head of string", args(1,2, batarg("",int),batarg("s",str))),
    4994             :  pattern("batstr", "ascii", STRbatAscii, false, "Return unicode of head of string", args(1,3, batarg("",int),batarg("s",str),batarg("s",oid))),
    4995             :  pattern("batstr", "substring", STRbatsubstringTail, false, "Extract the tail of a string", args(1,3, batarg("",str),batarg("s",str),batarg("start",int))),
    4996             :  pattern("batstr", "substring", STRbatsubstringTail, false, "Extract the tail of a string", args(1,5, batarg("",str),batarg("s",str),batarg("start",int),batarg("s1",oid),batarg("s2",oid))),
    4997             :  pattern("batstr", "substring", STRbatsubstringTailcst, false, "Extract the tail of a string", args(1,3, batarg("",str),batarg("s",str),arg("start",int))),
    4998             :  pattern("batstr", "substring", STRbatsubstringTailcst, false, "Extract the tail of a string", args(1,4, batarg("",str),batarg("s",str),arg("start",int),batarg("s",oid))),
    4999             :  pattern("batstr", "substring", STRbatsubstringTail_strcst, false, "Extract the tail of a string", args(1,3, batarg("",str),arg("s",str),batarg("start",int))),
    5000             :  pattern("batstr", "substring", STRbatsubstringTail_strcst, false, "Extract the tail of a string", args(1,4, batarg("",str),arg("s",str),batarg("start",int),batarg("s",oid))),
    5001             :  pattern("batstr", "substring3", STRbatsubstring, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),batarg("s",str),batarg("start",int),batarg("index",int))),
    5002             :  pattern("batstr", "substring3", STRbatsubstring, false, "Substring extraction using [start,start+length]", args(1,7, batarg("",str),batarg("s",str),batarg("start",int),batarg("index",int),batarg("s1",oid),batarg("s2",oid),batarg("s3",oid))),
    5003             :  pattern("batstr", "substring3", STRbatsubstring_2nd_3rd_cst, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),batarg("s",str),arg("start",int),arg("index",int))),
    5004             :  pattern("batstr", "substring3", STRbatsubstring_2nd_3rd_cst, false, "Substring extraction using [start,start+length]", args(1,5, batarg("",str),batarg("s",str),arg("start",int),arg("index",int),batarg("s",oid))),
    5005             :  pattern("batstr", "substring3", STRbatsubstring_2nd_cst, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),batarg("s",str),arg("start",int),batarg("index",int))),
    5006             :  pattern("batstr", "substring3", STRbatsubstring_2nd_cst, false, "Substring extraction using [start,start+length]", args(1,6, batarg("",str),batarg("s",str),arg("start",int),batarg("index",int),batarg("s1",oid),batarg("s2",oid))),
    5007             :  pattern("batstr", "substring3", STRbatsubstring_3rd_cst, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),batarg("s",str),batarg("start",int),arg("index",int))),
    5008             :  pattern("batstr", "substring3", STRbatsubstring_3rd_cst, false, "Substring extraction using [start,start+length]", args(1,6, batarg("",str),batarg("s",str),batarg("start",int),arg("index",int),batarg("s1",oid),batarg("s2",oid))),
    5009             :  pattern("batstr", "substring3", STRbatsubstring_1st_2nd_cst, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),arg("s",str),arg("start",int),batarg("index",int))),
    5010             :  pattern("batstr", "substring3", STRbatsubstring_1st_2nd_cst, false, "Substring extraction using [start,start+length]", args(1,5, batarg("",str),arg("s",str),arg("start",int),batarg("index",int),batarg("s",oid))),
    5011             :  pattern("batstr", "substring3", STRbatsubstring_1st_3rd_cst, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),arg("s",str),batarg("start",int),arg("index",int))),
    5012             :  pattern("batstr", "substring3", STRbatsubstring_1st_3rd_cst, false, "Substring extraction using [start,start+length]", args(1,5, batarg("",str),arg("s",str),batarg("start",int),arg("index",int),batarg("s",oid))),
    5013             :  pattern("batstr", "substring3", STRbatsubstring_1st_cst, false, "Substring extraction using [start,start+length]", args(1,4, batarg("",str),arg("s",str),batarg("start",int),batarg("index",int))),
    5014             :  pattern("batstr", "substring3", STRbatsubstring_1st_cst, false, "Substring extraction using [start,start+length]", args(1,6, batarg("",str),arg("s",str),batarg("start",int),batarg("index",int),batarg("s1",oid),batarg("s2",oid))),
    5015             :  pattern("batstr", "unicode", STRbatFromWChr, false, "convert a unicode to a character.", args(1,2, batarg("",str),batarg("wchar",int))),
    5016             :  pattern("batstr", "unicode", STRbatFromWChr, false, "convert a unicode to a character.", args(1,3, batarg("",str),batarg("wchar",int),batarg("s",oid))),
    5017             :  pattern("batstr", "unicodeAt", STRbatWChrAt, false, "get a unicode character (as an int) from a string position.", args(1,3, batarg("",int),batarg("s",str),batarg("index",int))),
    5018             :  pattern("batstr", "unicodeAt", STRbatWChrAt, false, "get a unicode character (as an int) from a string position.", args(1,5, batarg("",int),batarg("s",str),batarg("index",int),batarg("s1",oid),batarg("s2",oid))),
    5019             :  pattern("batstr", "unicodeAt", STRbatWChrAtcst, false, "get a unicode character (as an int) from a string position.", args(1,3, batarg("",int),batarg("s",str),arg("index",int))),
    5020             :  pattern("batstr", "unicodeAt", STRbatWChrAtcst, false, "get a unicode character (as an int) from a string position.", args(1,4, batarg("",int),batarg("s",str),arg("index",int),batarg("s",oid))),
    5021             :  pattern("batstr", "unicodeAt", STRbatWChrAt_strcst, false, "get a unicode character (as an int) from a string position.", args(1,3, batarg("",int),arg("s",str),batarg("index",int))),
    5022             :  pattern("batstr", "unicodeAt", STRbatWChrAt_strcst, false, "get a unicode character (as an int) from a string position.", args(1,4, batarg("",int),arg("s",str),batarg("index",int),batarg("s",oid))),
    5023             :  pattern("batstr", "substitute", STRbatSubstitute, false, "Substitute first occurrence of 'src' by\n'dst'. Iff repeated = true this is\nrepeated while 'src' can be found in the\nresult string. In order to prevent\nrecursion and result strings of unlimited\nsize, repeating is only done iff src is\nnot a substring of dst.", args(1,5, batarg("",str),batarg("s",str),batarg("src",str),batarg("dst",str),batarg("rep",bit))),
    5024             :  pattern("batstr", "substitute", STRbatSubstitutecst, false, "Substitute first occurrence of 'src' by\n'dst'. Iff repeated = true this is\nrepeated while 'src' can be found in the\nresult string. In order to prevent\nrecursion and result strings of unlimited\nsize, repeating is only done iff src is\nnot a substring of dst.", args(1,5, batarg("",str),batarg("s",str),arg("src",str),arg("dst",str),arg("rep",bit))),
    5025             :  pattern("batstr", "stringleft", STRbatprefix, false, "", args(1,3, batarg("",str),batarg("s",str),batarg("l",int))),
    5026             :  pattern("batstr", "stringleft", STRbatprefix, false, "", args(1,5, batarg("",str),batarg("s",str),batarg("l",int),batarg("s1",oid),batarg("s2",oid))),
    5027             :  pattern("batstr", "stringleft", STRbatprefixcst, false, "", args(1,3, batarg("",str),batarg("s",str),arg("l",int))),
    5028             :  pattern("batstr", "stringleft", STRbatprefixcst, false, "", args(1,4, batarg("",str),batarg("s",str),arg("l",int),batarg("s",oid))),
    5029             :  pattern("batstr", "stringleft", STRbatprefix_strcst, false, "", args(1,3, batarg("",str),arg("s",str),batarg("l",int))),
    5030             :  pattern("batstr", "stringleft", STRbatprefix_strcst, false, "", args(1,4, batarg("",str),arg("s",str),batarg("l",int),batarg("s",oid))),
    5031             :  pattern("batstr", "stringright", STRbatsuffix, false, "", args(1,3, batarg("",str),batarg("s",str),batarg("l",int))),
    5032             :  pattern("batstr", "stringright", STRbatsuffix, false, "", args(1,5, batarg("",str),batarg("s",str),batarg("l",int),batarg("s1",oid),batarg("s2",oid))),
    5033             :  pattern("batstr", "stringright", STRbatsuffixcst, false, "", args(1,3, batarg("",str),batarg("s",str),arg("l",int))),
    5034             :  pattern("batstr", "stringright", STRbatsuffixcst, false, "", args(1,4, batarg("",str),batarg("s",str),arg("l",int),batarg("s",oid))),
    5035             :  pattern("batstr", "stringright", STRbatsuffix_strcst, false, "", args(1,3, batarg("",str),arg("s",str),batarg("l",int))),
    5036             :  pattern("batstr", "stringright", STRbatsuffix_strcst, false, "", args(1,4, batarg("",str),arg("s",str),batarg("l",int),batarg("s",oid))),
    5037             :  pattern("batstr", "locate", STRbatstrLocate, false, "Locate the start position of a string", args(1,3, batarg("",int),batarg("s1",str),batarg("s2",str))),
    5038             :  pattern("batstr", "locate", STRbatstrLocate, false, "Locate the start position of a string", args(1,5, batarg("",int),batarg("s1",str),batarg("s2",str),batarg("s1",oid),batarg("s2",oid))),
    5039             :  pattern("batstr", "locate", STRbatstrLocatecst, false, "Locate the start position of a string", args(1,3, batarg("",int),batarg("s1",str),arg("s2",str))),
    5040             :  pattern("batstr", "locate", STRbatstrLocatecst, false, "Locate the start position of a string", args(1,4, batarg("",int),batarg("s1",str),arg("s2",str),batarg("s",oid))),
    5041             :  pattern("batstr", "locate", STRbatstrLocate_strcst, false, "Locate the start position of a string", args(1,3, batarg("",int),arg("s1",str),batarg("s2",str))),
    5042             :  pattern("batstr", "locate", STRbatstrLocate_strcst, false, "Locate the start position of a string", args(1,4, batarg("",int),arg("s1",str),batarg("s2",str),batarg("s",oid))),
    5043             :  pattern("batstr", "locate3", STRbatstrLocate3, false, "Locate the start position of a string", args(1,4, batarg("",int),batarg("s1",str),batarg("s2",str),batarg("start",int))),
    5044             :  pattern("batstr", "locate3", STRbatstrLocate3cst, false, "Locate the start position of a string", args(1,4, batarg("",int),batarg("s1",str),arg("s2",str),arg("start",int))),
    5045             :  pattern("batstr", "insert", STRbatInsert, false, "Insert a string into another", args(1,5, batarg("",str),batarg("s",str),batarg("start",int),batarg("l",int),batarg("s2",str))),
    5046             :  pattern("batstr", "insert", STRbatInsertcst, false, "Insert a string into another", args(1,5, batarg("",str),batarg("s",str),arg("start",int),arg("l",int),arg("s2",str))),
    5047             :  pattern("batstr", "replace", STRbatReplace, false, "Insert a string into another", args(1,4, batarg("",str),batarg("s",str),batarg("pat",str),batarg("s2",str))),
    5048             :  pattern("batstr", "replace", STRbatReplacecst, false, "Insert a string into another", args(1,4, batarg("",str),batarg("s",str),arg("pat",str),arg("s2",str))),
    5049             :  pattern("batstr", "repeat", STRbatrepeat, false, "", args(1,3, batarg("",str),batarg("s",str),batarg("c",int))),
    5050             :  pattern("batstr", "repeat", STRbatrepeat, false, "", args(1,5, batarg("",str),batarg("s",str),batarg("c",int),batarg("s1",oid),batarg("s2",oid))),
    5051             :  pattern("batstr", "repeat", STRbatrepeatcst, false, "", args(1,3, batarg("",str),batarg("s",str),arg("c",int))),
    5052             :  pattern("batstr", "repeat", STRbatrepeatcst, false, "", args(1,4, batarg("",str),batarg("s",str),arg("c",int),batarg("s",oid))),
    5053             :  pattern("batstr", "repeat", STRbatrepeat_strcst, false, "", args(1,3, batarg("",str),arg("s",str),batarg("c",int))),
    5054             :  pattern("batstr", "repeat", STRbatrepeat_strcst, false, "", args(1,4, batarg("",str),arg("s",str),batarg("c",int),batarg("s",oid))),
    5055             :  pattern("batstr", "space", STRbatSpace, false, "", args(1,2, batarg("",str),batarg("l",int))),
    5056             :  pattern("batstr", "space", STRbatSpace, false, "", args(1,3, batarg("",str),batarg("l",int),batarg("s",oid))),
    5057             :  { .imp=NULL }
    5058             : };
    5059             : #include "mal_import.h"
    5060             : #ifdef _MSC_VER
    5061             : #undef read
    5062             : #pragma section(".CRT$XCU",read)
    5063             : #endif
    5064         259 : LIB_STARTUP_FUNC(init_batstr_mal)
    5065         259 : { mal_module("batstr", NULL, batstr_init_funcs); }

Generated by: LCOV version 1.14