LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_rank.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 773 1122 68.9 %
Date: 2021-10-13 02:24:04 Functions: 38 38 100.0 %

          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             : #include "monetdb_config.h"
      10             : #include "sql_rank.h"
      11             : #include "gdk_analytic.h"
      12             : 
      13             : static void
      14        3309 : unfix_inputs(int nargs, ...)
      15             : {
      16             :         va_list valist;
      17             : 
      18        3309 :         va_start(valist, nargs);
      19       14059 :         for (int i = 0; i < nargs; i++) {
      20       10750 :                 BAT *b = va_arg(valist, BAT *);
      21       10751 :                 if (b)
      22        5576 :                         BBPunfix(b->batCacheid);
      23             :         }
      24        3309 :         va_end(valist);
      25        3309 : }
      26             : 
      27             : static void
      28        3124 : finalize_output(bat *res, BAT *r, str msg)
      29             : {
      30        3124 :         if (res && r && !msg) {
      31        2985 :                 r->tsorted = BATcount(r) <= 1;
      32        2985 :                 r->trevsorted = BATcount(r) <= 1;
      33        2985 :                 r->tkey = BATcount(r) <= 1;
      34        2985 :                 BBPkeepref(*res = r->batCacheid);
      35         139 :         } else if (r)
      36          10 :                 BBPreclaim(r);
      37        3124 : }
      38             : 
      39             : str
      40        1218 : SQLdiff(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      41             : {
      42             :         BAT *r = NULL, *b = NULL, *c = NULL;
      43             :         bat *res = NULL;
      44             :         str msg = MAL_SUCCEED;
      45             : 
      46             :         (void)cntxt;
      47        1218 :         if (isaBatType(getArgType(mb, pci, 1))) {
      48             :                 gdk_return gdk_code = GDK_SUCCEED;
      49             : 
      50        1191 :                 res = getArgReference_bat(stk, pci, 0);
      51        1191 :                 if (pci->argc > 2) {
      52          79 :                         if (isaBatType(getArgType(mb, pci, 2))) {
      53          79 :                                 if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
      54           0 :                                         msg = createException(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor");
      55           0 :                                         goto bailout;
      56             :                                 }
      57          79 :                                 if (!(r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT))) {
      58           0 :                                         msg = createException(SQL, "sql.diff", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      59           0 :                                         goto bailout;
      60             :                                 }
      61             :                                 c = b;
      62          79 :                                 if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 2))))) {
      63           0 :                                         msg = createException(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor");
      64           0 :                                         goto bailout;
      65             :                                 }
      66          79 :                                 gdk_code = GDKanalyticaldiff(r, b, c, NULL, b->ttype);
      67             :                         } else { /* the input is a constant, so the output is the previous sql.diff output */
      68           0 :                                 BBPretain(*res = *getArgReference_bat(stk, pci, 1));
      69           0 :                                 return MAL_SUCCEED;
      70             :                         }
      71             :                 } else {
      72        1112 :                         if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
      73           0 :                                 msg = createException(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor");
      74           0 :                                 goto bailout;
      75             :                         }
      76        1112 :                         if (!(r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT))) {
      77           0 :                                 msg = createException(SQL, "sql.diff", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      78           0 :                                 goto bailout;
      79             :                         }
      80        1112 :                         gdk_code = GDKanalyticaldiff(r, b, NULL, NULL, b->ttype);
      81             :                 }
      82        1191 :                 if (gdk_code != GDK_SUCCEED)
      83           0 :                         msg = createException(SQL, "sql.diff", GDK_EXCEPTION);
      84          27 :         } else if (pci->argc > 2 && isaBatType(getArgType(mb, pci, 2))) {
      85           0 :                 bit *restrict prev = getArgReference_bit(stk, pci, 1);
      86             : 
      87           0 :                 res = getArgReference_bat(stk, pci, 0);
      88           0 :                 if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 2))))) {
      89           0 :                         msg = createException(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor");
      90           0 :                         goto bailout;
      91             :                 }
      92           0 :                 if (!(r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT))) {
      93           0 :                         msg = createException(SQL, "sql.diff", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      94           0 :                         goto bailout;
      95             :                 }
      96             : 
      97           0 :                 if (GDKanalyticaldiff(r, b, NULL, prev, b->ttype) != GDK_SUCCEED)
      98           0 :                         msg = createException(SQL, "sql.diff", GDK_EXCEPTION);
      99             :         } else {
     100          27 :                 bit *res = getArgReference_bit(stk, pci, 0);
     101          27 :                 *res = FALSE;
     102             :         }
     103             : 
     104        1218 : bailout:
     105        1218 :         unfix_inputs(2, b, c);
     106        1218 :         finalize_output(res, r, msg);
     107        1218 :         return msg;
     108             : }
     109             : 
     110             : str
     111         778 : SQLwindow_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     112             : {
     113             :         str msg = MAL_SUCCEED;
     114             :         bool preceding;
     115             :         oid second_half;
     116         778 :         int unit, bound, excl, part_offset = (pci->argc > 6);
     117             :         bat *res = NULL;
     118             :         BAT *r = NULL, *b = NULL, *p = NULL, *l = NULL;
     119             : 
     120         778 :         if ((pci->argc != 6 && pci->argc != 7) || getArgType(mb, pci, part_offset + 2) != TYPE_int ||
     121         778 :                 getArgType(mb, pci, part_offset + 3) != TYPE_int || getArgType(mb, pci, part_offset + 4) != TYPE_int) {
     122           0 :                 throw(SQL, "sql.window_bound", SQLSTATE(42000) "Invalid arguments");
     123             :         }
     124             : 
     125         778 :         unit = *getArgReference_int(stk, pci, part_offset + 2);
     126         778 :         bound = *getArgReference_int(stk, pci, part_offset + 3);
     127         778 :         excl = *getArgReference_int(stk, pci, part_offset + 4);
     128             : 
     129         778 :         assert(unit >= 0 && unit <= 3);
     130         778 :         assert(bound >= 0 && bound <= 5);
     131         778 :         assert(excl >= 0 && excl <= 2);
     132         778 :         preceding = (bound % 2 == 0);
     133         778 :         second_half = !(bound < 2 || bound == 4);
     134             : 
     135             :         (void)cntxt;
     136         778 :         if (isaBatType(getArgType(mb, pci, 1))) {
     137         744 :                 int tp1, tp2 = getArgType(mb, pci, part_offset + 5);
     138             :                 ptr limit = NULL;
     139             :                 bool is_a_bat;
     140             : 
     141         744 :                 res = getArgReference_bat(stk, pci, 0);
     142         744 :                 if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 1))))) {
     143           0 :                         msg = createException(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor");
     144           0 :                         goto bailout;
     145             :                 }
     146         743 :                 tp1 = b->ttype;
     147             : 
     148         743 :                 if (excl != 0) {
     149           0 :                         msg = createException(SQL, "sql.window_bound", SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented");
     150           0 :                         goto bailout;
     151             :                 }
     152             : 
     153         743 :                 is_a_bat = isaBatType(tp2);
     154         743 :                 if (is_a_bat)
     155          11 :                         tp2 = getBatType(tp2);
     156             : 
     157         743 :                 if (!(r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT))) {
     158           0 :                         msg = createException(SQL, "sql.window_bound", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     159           0 :                         goto bailout;
     160             :                 }
     161         744 :                 if (is_a_bat) { //SQL_CURRENT_ROW shall never fall in limit validation
     162          11 :                         if ((!(l = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 5))))) {
     163           0 :                                 msg = createException(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor");
     164           0 :                                 goto bailout;
     165             :                         }
     166             :                 } else {
     167         733 :                         limit = getArgReference(stk, pci, part_offset + 5);
     168             :                 }
     169         744 :                 if (part_offset) {
     170         350 :                         if ((!(p = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
     171           0 :                                 msg = createException(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor");
     172           0 :                                 goto bailout;
     173             :                         }
     174             :                 }
     175             : 
     176             :                 //On RANGE frame, when "CURRENT ROW" is not specified, the ranges are calculated with SQL intervals in mind
     177         744 :                 if (GDKanalyticalwindowbounds(r, b, p, l, limit, tp1, tp2, unit, preceding, second_half) != GDK_SUCCEED)
     178           6 :                         msg = createException(SQL, "sql.window_bound", GDK_EXCEPTION);
     179             :         } else {
     180          34 :                 oid *res = getArgReference_oid(stk, pci, 0);
     181             : 
     182          34 :                 *res = preceding ? 0 : 1;
     183             :         }
     184             : 
     185         777 : bailout:
     186         777 :         unfix_inputs(3, b, p, l);
     187         778 :         finalize_output(res, r, msg);
     188         778 :         return msg;
     189             : }
     190             : 
     191             : str
     192          53 : SQLrow_number(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     193             : {
     194             :         BAT *r = NULL, *b = NULL, *p = NULL;
     195             :         bat *res = NULL;
     196             :         str msg = MAL_SUCCEED;
     197             : 
     198          53 :         if (pci->argc != 4 ||
     199          53 :                 (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
     200          53 :                 (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
     201           0 :                 throw(SQL, "sql.row_number", SQLSTATE(42000) "row_number(:any_1,:bit,:bit)");
     202             :         }
     203             :         (void)cntxt;
     204          53 :         if (isaBatType(getArgType(mb, pci, 1))) {
     205             :                 BUN cnt;
     206             :                 int j, *rp, *end;
     207             :                 bit *np;
     208             : 
     209          51 :                 res = getArgReference_bat(stk, pci, 0);
     210          51 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     211           0 :                         msg = createException(SQL, "sql.row_number", SQLSTATE(HY005) "Cannot access column descriptor");
     212           0 :                         goto bailout;
     213             :                 }
     214          51 :                 if (!(r = COLnew(b->hseqbase, TYPE_int, BATcount(b), TRANSIENT))) {
     215           0 :                         msg = createException(SQL, "sql.row_number", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     216           0 :                         goto bailout;
     217             :                 }
     218          51 :                 r->tsorted = r->trevsorted = BATcount(b) <= 1;
     219             : 
     220             :                 cnt = BATcount(b);
     221          51 :                 rp = (int*)Tloc(r, 0);
     222          72 :                 if (isaBatType(getArgType(mb, pci, 2))) {
     223             :                         /* order info not used */
     224          21 :                         if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
     225           0 :                                 msg = createException(SQL, "sql.row_number", SQLSTATE(HY005) "Cannot access column descriptor");
     226           0 :                                 goto bailout;
     227             :                         }
     228          21 :                         BATiter pi = bat_iterator(p);
     229          21 :                         np = (bit*)pi.base;
     230          21 :                         end = rp + cnt;
     231     1248276 :                         for(j=1; rp<end; j++, np++, rp++) {
     232     1248255 :                                 if (*np)
     233             :                                         j=1;
     234     1248255 :                                 *rp = j;
     235             :                         }
     236          21 :                         bat_iterator_end(&pi);
     237             :                 } else { /* single value, ie no partitions, order info not used */
     238          30 :                         int icnt = (int) cnt;
     239    20099626 :                         for(j=1; j<=icnt; j++, rp++)
     240    20099596 :                                 *rp = j;
     241          30 :                         r->tsorted = true;
     242          30 :                         r->tkey = true;
     243             :                 }
     244          51 :                 BATsetcount(r, cnt);
     245          51 :                 r->tnonil = true;
     246          51 :                 r->tnil = false;
     247             :         } else {
     248           2 :                 int *res = getArgReference_int(stk, pci, 0);
     249             : 
     250           2 :                 *res = 1;
     251             :         }
     252             : 
     253          53 : bailout:
     254          53 :         unfix_inputs(2, b, p);
     255          53 :         if (res && r && !msg) {
     256          51 :                 r->tkey = BATcount(r) <= 1;
     257          51 :                 BBPkeepref(*res = r->batCacheid);
     258           2 :         } else if (r)
     259           0 :                 BBPreclaim(r);
     260             :         return msg;
     261             : }
     262             : 
     263             : str
     264          79 : SQLrank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     265             : {
     266             :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
     267             :         bat *res = NULL;
     268             :         str msg = MAL_SUCCEED;
     269             : 
     270          79 :         if (pci->argc != 4 ||
     271          79 :                 (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
     272          79 :                 (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
     273           0 :                 throw(SQL, "sql.rank", SQLSTATE(42000) "rank(:any_1,:bit,:bit)");
     274             :         }
     275             :         (void)cntxt;
     276          79 :         if (isaBatType(getArgType(mb, pci, 1))) {
     277             :                 BUN cnt;
     278             :                 int j, k, *rp, *end;
     279             :                 bit *np, *no;
     280             : 
     281          69 :                 res = getArgReference_bat(stk, pci, 0);
     282          69 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     283           0 :                         msg = createException(SQL, "sql.rank", SQLSTATE(HY005) "Cannot access column descriptor");
     284           0 :                         goto bailout;
     285             :                 }
     286          69 :                 if (!(r = COLnew(b->hseqbase, TYPE_int, BATcount(b), TRANSIENT))) {
     287           0 :                         msg = createException(SQL, "sql.rank", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     288           0 :                         goto bailout;
     289             :                 }
     290          69 :                 r->tsorted = r->trevsorted = BATcount(b) <= 1;
     291             : 
     292             :                 cnt = BATcount(b);
     293          69 :                 rp = (int*)Tloc(r, 0);
     294          69 :                 end = rp + cnt;
     295          69 :                 if (isaBatType(getArgType(mb, pci, 2))) {
     296          54 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     297          21 :                                 if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     298           0 :                                         msg = createException(SQL, "sql.rank", SQLSTATE(HY005) "Cannot access column descriptor");
     299           0 :                                         goto bailout;
     300             :                                 }
     301          21 :                                 BATiter pi = bat_iterator(p);
     302          21 :                                 BATiter oi = bat_iterator(o);
     303          21 :                                 np = (bit*)pi.base;
     304          21 :                                 no = (bit*)oi.base;
     305     1109264 :                                 for(j=1,k=1; rp<end; k++, np++, no++, rp++) {
     306     1109243 :                                         if (*np)
     307             :                                                 j=k=1;
     308     1109243 :                                         if (*no)
     309             :                                                 j=k;
     310     1109243 :                                         *rp = j;
     311             :                                 }
     312          21 :                                 bat_iterator_end(&pi);
     313          21 :                                 bat_iterator_end(&oi);
     314             :                         } else { /* single value, ie no ordering */
     315          12 :                                 if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
     316           0 :                                         msg = createException(SQL, "sql.rank", SQLSTATE(HY005) "Cannot access column descriptor");
     317           0 :                                         goto bailout;
     318             :                                 }
     319          12 :                                 BATiter pi = bat_iterator(p);
     320             :                                 np = (bit*)pi.base;
     321         174 :                                 for(j=1; rp<end; np++, rp++) {
     322             :                                         if (*np)
     323             :                                                 j=1;
     324         162 :                                         *rp = j;
     325             :                                 }
     326          12 :                                 bat_iterator_end(&pi);
     327             :                         }
     328             :                 } else { /* single value, ie no partitions */
     329          48 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     330          12 :                                 if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     331           0 :                                         msg = createException(SQL, "sql.rank", SQLSTATE(HY005) "Cannot access column descriptor");
     332           0 :                                         goto bailout;
     333             :                                 }
     334          12 :                                 BATiter oi = bat_iterator(o);
     335          12 :                                 no = (bit*)oi.base;
     336       16498 :                                 for(j=1,k=1; rp<end; k++, no++, rp++) {
     337       16486 :                                         if (*no)
     338             :                                                 j=k;
     339       16486 :                                         *rp = j;
     340             :                                 }
     341          12 :                                 bat_iterator_end(&oi);
     342             :                         } else { /* single value, ie no ordering */
     343         178 :                                 for(; rp<end; rp++)
     344         154 :                                         *rp = 1;
     345          24 :                                 r->tsorted = true;
     346          24 :                                 r->trevsorted = true;
     347             :                         }
     348             :                 }
     349          69 :                 BATsetcount(r, cnt);
     350          69 :                 r->tnonil = true;
     351          69 :                 r->tnil = false;
     352             :         } else {
     353          10 :                 int *res = getArgReference_int(stk, pci, 0);
     354             : 
     355          10 :                 *res = 1;
     356             :         }
     357             : 
     358          79 : bailout:
     359          79 :         unfix_inputs(3, b, p, o);
     360          79 :         if (res && r && !msg) {
     361          69 :                 r->tkey = BATcount(r) <= 1;
     362          69 :                 BBPkeepref(*res = r->batCacheid);
     363          10 :         } else if (r)
     364           0 :                 BBPreclaim(r);
     365             :         return msg;
     366             : }
     367             : 
     368             : str
     369          19 : SQLdense_rank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     370             : {
     371             :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
     372             :         bat *res = NULL;
     373             :         str msg = MAL_SUCCEED;
     374             : 
     375          19 :         if (pci->argc != 4 ||
     376          19 :                 (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
     377          19 :                 (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
     378           0 :                 throw(SQL, "sql.dense_rank", SQLSTATE(42000) "dense_rank(:any_1,:bit,:bit)");
     379             :         }
     380             :         (void)cntxt;
     381          19 :         if (isaBatType(getArgType(mb, pci, 1))) {
     382             :                 BUN cnt;
     383             :                 int j, *rp, *end;
     384             :                 bit *np, *no;
     385             : 
     386          18 :                 res = getArgReference_bat(stk, pci, 0);
     387          18 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     388           0 :                         msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     389           0 :                         goto bailout;
     390             :                 }
     391          18 :                 if (!(r = COLnew(b->hseqbase, TYPE_int, BATcount(b), TRANSIENT))) {
     392           0 :                         msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     393           0 :                         goto bailout;
     394             :                 }
     395          18 :                 r->tsorted = r->trevsorted = BATcount(b) <= 1;
     396             : 
     397             :                 cnt = BATcount(b);
     398          18 :                 rp = (int*)Tloc(r, 0);
     399          18 :                 end = rp + cnt;
     400          18 :                 if (isaBatType(getArgType(mb, pci, 2))) {
     401          17 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     402           6 :                                 if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     403           0 :                                         msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     404           0 :                                         goto bailout;
     405             :                                 }
     406           6 :                                 BATiter pi = bat_iterator(p);
     407           6 :                                 BATiter oi = bat_iterator(o);
     408           6 :                                 np = (bit*)pi.base;
     409           6 :                                 no = (bit*)oi.base;
     410         210 :                                 for(j=1; rp<end; np++, no++, rp++) {
     411         204 :                                         if (*np)
     412             :                                                 j=1;
     413         189 :                                         else if (*no)
     414          12 :                                                 j++;
     415         204 :                                         *rp = j;
     416             :                                 }
     417           6 :                                 bat_iterator_end(&pi);
     418           6 :                                 bat_iterator_end(&oi);
     419             :                         } else { /* single value, ie no ordering */
     420           5 :                                 if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
     421           0 :                                         msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     422           0 :                                         goto bailout;
     423             :                                 }
     424           5 :                                 BATiter pi = bat_iterator(p);
     425             :                                 np = (bit*)pi.base;
     426         105 :                                 for(j=1; rp<end; np++, rp++) {
     427             :                                         if (*np)
     428             :                                                 j=1;
     429         100 :                                         *rp = j;
     430             :                                 }
     431           5 :                                 bat_iterator_end(&pi);
     432             :                         }
     433             :                 } else { /* single value, ie no partitions */
     434          12 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     435           5 :                                 if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     436           0 :                                         msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     437           0 :                                         goto bailout;
     438             :                                 }
     439           5 :                                 BATiter oi = bat_iterator(o);
     440           5 :                                 no = (bit*)oi.base;
     441          62 :                                 for(j=1; rp<end; no++, rp++) {
     442          57 :                                         if (*no)
     443          32 :                                                 j++;
     444          57 :                                         *rp = j;
     445             :                                 }
     446           5 :                                 bat_iterator_end(&oi);
     447             :                         } else { /* single value, ie no ordering */
     448          39 :                                 for(; rp<end; rp++)
     449          37 :                                         *rp = 1;
     450           2 :                                 r->tsorted = true;
     451           2 :                                 r->trevsorted = true;
     452             :                         }
     453             :                 }
     454          18 :                 BATsetcount(r, cnt);
     455          18 :                 r->tnonil = true;
     456          18 :                 r->tnil = false;
     457             :         } else {
     458           1 :                 int *res = getArgReference_int(stk, pci, 0);
     459             : 
     460           1 :                 *res = 1;
     461             :         }
     462             : 
     463          19 : bailout:
     464          19 :         unfix_inputs(3, b, p, o);
     465          19 :         if (res && r && !msg) {
     466          18 :                 r->tkey = BATcount(r) <= 1;
     467          18 :                 BBPkeepref(*res = r->batCacheid);
     468           1 :         } else if (r)
     469           0 :                 BBPreclaim(r);
     470             :         return msg;
     471             : }
     472             : 
     473             : str
     474          16 : SQLpercent_rank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     475             : {
     476             :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
     477             :         bat *res = NULL;
     478             :         str msg = MAL_SUCCEED;
     479             : 
     480          16 :         if (pci->argc != 4 ||
     481          16 :                 (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
     482          16 :                 (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
     483           0 :                 throw(SQL, "sql.percent_rank", SQLSTATE(42000) "percent_rank(:any_1,:bit,:bit)");
     484             :         }
     485             :         (void)cntxt;
     486          16 :         if (isaBatType(getArgType(mb, pci, 1))) {
     487             :                 BUN ncnt, cnt;
     488             :                 int j, k;
     489             :                 dbl *rp, *end, cnt_cast;
     490             :                 bit *np, *np2, *no, *no2;
     491             : 
     492          16 :                 res = getArgReference_bat(stk, pci, 0);
     493          16 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     494           0 :                         msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     495           0 :                         goto bailout;
     496             :                 }
     497          16 :                 if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
     498           0 :                         msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     499           0 :                         goto bailout;
     500             :                 }
     501          16 :                 r->tsorted = r->trevsorted = BATcount(b) <= 1;
     502             : 
     503             :                 cnt = BATcount(b);
     504          16 :                 rp = (dbl*)Tloc(r, 0);
     505          16 :                 end = rp + cnt;
     506          16 :                 if (isaBatType(getArgType(mb, pci, 2))) {
     507          15 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     508           6 :                                 if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     509           0 :                                         msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     510           0 :                                         goto bailout;
     511             :                                 }
     512           6 :                                 BATiter pi = bat_iterator(p);
     513           6 :                                 np = (bit*)pi.base;
     514           6 :                                 np2 = np + BATcount(p);
     515           6 :                                 BATiter oi = bat_iterator(o);
     516           6 :                                 no2 = no = (bit*)oi.base;
     517             : 
     518         762 :                                 for (; np<np2; np++, no++) {
     519         756 :                                         if (*np) {
     520          38 :                                                 ncnt = no - no2;
     521          38 :                                                 if (ncnt == 1) {
     522          28 :                                                         for (; no2<no; no2++, rp++)
     523          14 :                                                                 *rp = 0.0;
     524             :                                                 } else {
     525          24 :                                                         cnt_cast = (dbl) (ncnt - 1);
     526             :                                                         j = 0;
     527             :                                                         k = 0;
     528         757 :                                                         for (; no2<no; k++, no2++, rp++) {
     529         733 :                                                                 if (*no2)
     530             :                                                                         j=k;
     531         733 :                                                                 *rp = j / cnt_cast;
     532             :                                                         }
     533             :                                                 }
     534             :                                         }
     535             :                                 }
     536           6 :                                 bat_iterator_end(&pi);
     537           6 :                                 ncnt = no - no2;
     538           6 :                                 if (ncnt == 1) {
     539           8 :                                         for (; no2<no; no2++, rp++)
     540           4 :                                                 *rp = 0.0;
     541             :                                 } else {
     542           2 :                                         cnt_cast = (dbl) (ncnt - 1);
     543             :                                         j = 0;
     544             :                                         k = 0;
     545           7 :                                         for (; no2<no; k++, no2++, rp++) {
     546           5 :                                                 if (*no2)
     547             :                                                         j=k;
     548           5 :                                                 *rp = j / cnt_cast;
     549             :                                         }
     550             :                                 }
     551           6 :                                 bat_iterator_end(&oi);
     552             :                         } else { /* single value, ie no ordering */
     553         381 :                                 for(; rp<end; rp++)
     554         378 :                                         *rp = 0.0;
     555           3 :                                 r->tsorted = true;
     556           3 :                                 r->trevsorted = true;
     557             :                         }
     558             :                 } else { /* single value, ie no partitions */
     559          13 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     560           6 :                                 if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     561           0 :                                         msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY005) "Cannot access column descriptor");
     562           0 :                                         goto bailout;
     563             :                                 }
     564           6 :                                 BATiter oi = bat_iterator(o);
     565           6 :                                 no = (bit*)oi.base;
     566             : 
     567           6 :                                 if (cnt == 1) {
     568           0 :                                         for (; rp<end; rp++)
     569           0 :                                                 *rp = 0.0;
     570           0 :                                         r->tsorted = true;
     571           0 :                                         r->trevsorted = true;
     572             :                                 } else {
     573           6 :                                         cnt_cast = (dbl) (cnt - 1);
     574         762 :                                         for(j=0,k=0; rp<end; k++, no++, rp++) {
     575         756 :                                                 if (*no)
     576             :                                                         j=k;
     577         756 :                                                 *rp = j / cnt_cast;
     578             :                                         }
     579             :                                 }
     580           6 :                                 bat_iterator_end(&oi);
     581             :                         } else { /* single value, ie no ordering */
     582          11 :                                 for(; rp<end; rp++)
     583          10 :                                         *rp = 0.0;
     584           1 :                                 r->tsorted = true;
     585           1 :                                 r->trevsorted = true;
     586             :                         }
     587             :                 }
     588          16 :                 BATsetcount(r, cnt);
     589          16 :                 r->tnonil = true;
     590          16 :                 r->tnil = false;
     591             :         } else {
     592           0 :                 dbl *res = getArgReference_dbl(stk, pci, 0);
     593             : 
     594           0 :                 *res = 0.0;
     595             :         }
     596             : 
     597          16 : bailout:
     598          16 :         unfix_inputs(3, b, p, o);
     599          16 :         if (res && r && !msg) {
     600          16 :                 r->tkey = BATcount(r) <= 1;
     601          16 :                 BBPkeepref(*res = r->batCacheid);
     602           0 :         } else if (r)
     603           0 :                 BBPreclaim(r);
     604             :         return msg;
     605             : }
     606             : 
     607             : str
     608          18 : SQLcume_dist(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     609             : {
     610             :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
     611             :         bat *res = NULL;
     612             :         str msg = MAL_SUCCEED;
     613             : 
     614          18 :         if (pci->argc != 4 ||
     615          18 :                 (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
     616          18 :                 (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
     617           0 :                 throw(SQL, "sql.cume_dist", SQLSTATE(42000) "cume_dist(:any_1,:bit,:bit)");
     618             :         }
     619             :         (void)cntxt;
     620          18 :         if (isaBatType(getArgType(mb, pci, 1))) {
     621             :                 BUN ncnt, j = 0;
     622             :                 bit *np, *no, *bo1, *bo2, *end;
     623             :                 dbl *rb, *rp, cnt_cast, nres;
     624             : 
     625          18 :                 res = getArgReference_bat(stk, pci, 0);
     626          18 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     627           0 :                         msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY005) "Cannot access column descriptor");
     628           0 :                         goto bailout;
     629             :                 }
     630          18 :                 if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
     631           0 :                         msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     632           0 :                         goto bailout;
     633             :                 }
     634          18 :                 r->tsorted = r->trevsorted = BATcount(b) <= 1;
     635             : 
     636          18 :                 rb = rp = (dbl*)Tloc(r, 0);
     637          18 :                 if (isaBatType(getArgType(mb, pci, 2))) {
     638          18 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     639           7 :                                 if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     640           0 :                                         msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY005) "Cannot access column descriptor");
     641           0 :                                         goto bailout;
     642             :                                 }
     643           7 :                                 BATiter pi = bat_iterator(p);
     644           7 :                                 np = (bit*)pi.base;
     645           7 :                                 end = np + BATcount(p);
     646           7 :                                 BATiter oi = bat_iterator(o);
     647           7 :                                 bo1 = bo2 = no = (bit*)oi.base;
     648             : 
     649         773 :                                 for (; np<end; np++, no++) {
     650         766 :                                         if (*np) {
     651          40 :                                                 ncnt = no - bo2;
     652          40 :                                                 cnt_cast = (dbl) ncnt;
     653             :                                                 j = 0;
     654         792 :                                                 for (; bo2<no; bo2++) {
     655         752 :                                                         if (*bo2) {
     656         368 :                                                                 j += (bo2 - bo1);
     657         368 :                                                                 nres = j / cnt_cast;
     658        1028 :                                                                 for (; bo1 < bo2; bo1++, rb++)
     659         660 :                                                                         *rb = nres;
     660             :                                                         }
     661             :                                                 }
     662         132 :                                                 for (; bo1 < bo2; bo1++, rb++)
     663          92 :                                                         *rb = 1.0;
     664             :                                         }
     665             :                                 }
     666             :                                 j = 0;
     667           7 :                                 ncnt = no - bo2;
     668           7 :                                 cnt_cast = (dbl) ncnt;
     669          21 :                                 for (; bo2<no; bo2++) {
     670          14 :                                         if (*bo2) {
     671          10 :                                                 j += (bo2 - bo1);
     672          10 :                                                 nres = j / cnt_cast;
     673          14 :                                                 for (; bo1 < bo2; bo1++, rb++)
     674           4 :                                                         *rb = nres;
     675             :                                         }
     676             :                                 }
     677          17 :                                 for (; bo1 < bo2; bo1++, rb++)
     678          10 :                                         *rb = 1.0;
     679           7 :                                 bat_iterator_end(&pi);
     680           7 :                                 bat_iterator_end(&oi);
     681             :                         } else { /* single value, ie no ordering */
     682           4 :                                 rp = rb + BATcount(b);
     683         392 :                                 for (; rb<rp; rb++)
     684         388 :                                         *rb = 1.0;
     685           4 :                                 r->tsorted = true;
     686           4 :                                 r->trevsorted = true;
     687             :                         }
     688             :                 } else { /* single value, ie no partitions */
     689          13 :                         if (isaBatType(getArgType(mb, pci, 3))) {
     690           6 :                                 if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     691           0 :                                         msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY005) "Cannot access column descriptor");
     692           0 :                                         goto bailout;
     693             :                                 }
     694           6 :                                 BATiter oi = bat_iterator(o);
     695           6 :                                 bo1 = bo2 = (bit*)oi.base;
     696           6 :                                 no = bo1 + BATcount(b);
     697           6 :                                 cnt_cast = (dbl) BATcount(b);
     698         762 :                                 for (; bo2<no; bo2++) {
     699         756 :                                         if (*bo2) {
     700         248 :                                                 j += (bo2 - bo1);
     701         248 :                                                 nres = j / cnt_cast;
     702         973 :                                                 for (; bo1 < bo2; bo1++, rb++)
     703         725 :                                                         *rb = nres;
     704             :                                         }
     705             :                                 }
     706          37 :                                 for (; bo1 < bo2; bo1++, rb++)
     707          31 :                                         *rb = 1.0;
     708           6 :                                 bat_iterator_end(&oi);
     709             :                         } else { /* single value, ie no ordering */
     710           1 :                                 rp = rb + BATcount(b);
     711          11 :                                 for (; rb<rp; rb++)
     712          10 :                                         *rb = 1.0;
     713           1 :                                 r->tsorted = true;
     714           1 :                                 r->trevsorted = true;
     715             :                         }
     716             :                 }
     717          18 :                 BATsetcount(r, BATcount(b));
     718          18 :                 r->tnonil = true;
     719          18 :                 r->tnil = false;
     720             :         } else {
     721           0 :                 dbl *res = getArgReference_dbl(stk, pci, 0);
     722             : 
     723           0 :                 *res = 1.0;
     724             :         }
     725             : 
     726          18 : bailout:
     727          18 :         unfix_inputs(3, b, p, o);
     728          18 :         if (res && r && !msg) {
     729          18 :                 r->tkey = BATcount(r) <= 1;
     730          18 :                 BBPkeepref(*res = r->batCacheid);
     731           0 :         } else if (r)
     732           0 :                 BBPreclaim(r);
     733             :         return msg;
     734             : }
     735             : 
     736             : #define NTILE_VALUE_SINGLE_IMP(TPE) \
     737             :         do { \
     738             :                 TPE val = *(TPE*) VALget(ntile); \
     739             :                 if (!is_##TPE##_nil(val) && val < 1) { \
     740             :                         msg = createException(SQL, "sql.ntile", SQLSTATE(42000) "ntile must be greater than zero"); \
     741             :                         goto bailout;   \
     742             :                 }       \
     743             :                 if (!is_##TPE##_nil(val)) \
     744             :                         val = 1; \
     745             :                 VALset(res, tp2, &val); \
     746             :         } while(0)
     747             : 
     748             : str
     749          61 : SQLntile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     750             : {
     751             :         BAT *r = NULL, *b = NULL, *p = NULL, *n = NULL;
     752             :         bat *res = NULL;
     753             :         str msg = MAL_SUCCEED;
     754             : 
     755             :         (void)cntxt;
     756          61 :         if (pci->argc != 5 || (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit) ||
     757          61 :                 (getArgType(mb, pci, 4) != TYPE_bit && getBatType(getArgType(mb, pci, 4)) != TYPE_bit)) {
     758           0 :                 throw(SQL, "sql.ntile", SQLSTATE(42000) "ntile(:any_1,:number,:bit,:bit)");
     759             :         }
     760             : 
     761          61 :         if (isaBatType(getArgType(mb, pci, 1))) {
     762             :                 int tp2 = 0;
     763             :                 ptr ntile = NULL;
     764          59 :                 res = getArgReference_bat(stk, pci, 0);
     765             : 
     766          59 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     767           0 :                         msg = createException(SQL, "sql.ntile", SQLSTATE(HY005) "Cannot access column descriptor");
     768           0 :                         goto bailout;
     769             :                 }
     770          59 :                 if (isaBatType(getArgType(mb, pci, 2))) {
     771          27 :                         tp2 = getBatType(getArgType(mb, pci, 2));
     772          27 :                         if (!(n = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
     773           0 :                                 msg = createException(SQL, "sql.ntile", SQLSTATE(HY005) "Cannot access column descriptor");
     774           0 :                                 goto bailout;
     775             :                         }
     776             :                 } else {
     777             :                         tp2 = getArgType(mb, pci, 2);
     778          32 :                         ntile = getArgReference(stk, pci, 2);
     779             :                 }
     780          59 :                 if (!(r = COLnew(b->hseqbase, tp2, BATcount(b), TRANSIENT))) {
     781           0 :                         msg = createException(SQL, "sql.ntile", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     782           0 :                         goto bailout;
     783             :                 }
     784          59 :                 if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
     785           0 :                         msg = createException(SQL, "sql.ntile", SQLSTATE(HY005) "Cannot access column descriptor");
     786           0 :                         goto bailout;
     787             :                 }
     788          59 :                 if ((p && BATcount(b) != BATcount(p)) || (n && BATcount(b) != BATcount(n))) {
     789           0 :                         msg = createException(SQL, "sql.ntile", ILLEGAL_ARGUMENT " Requires bats of identical size");
     790           0 :                         goto bailout;
     791             :                 }
     792             : 
     793          59 :                 if (GDKanalyticalntile(r, b, p, n, tp2, ntile) != GDK_SUCCEED)
     794           0 :                         msg = createException(SQL, "sql.ntile", GDK_EXCEPTION);
     795             :         } else {
     796           2 :                 ValRecord *res = &(stk)->stk[(pci)->argv[0]];
     797           2 :                 ValRecord *ntile = &(stk)->stk[(pci)->argv[2]];
     798           2 :                 int tp2 = getArgType(mb, pci, 2);
     799             : 
     800           2 :                 switch (tp2) {
     801           2 :                         case TYPE_bte:
     802           2 :                                 NTILE_VALUE_SINGLE_IMP(bte);
     803           2 :                                 break;
     804           0 :                         case TYPE_sht:
     805           0 :                                 NTILE_VALUE_SINGLE_IMP(sht);
     806           0 :                                 break;
     807           0 :                         case TYPE_int:
     808           0 :                                 NTILE_VALUE_SINGLE_IMP(int);
     809           0 :                                 break;
     810           0 :                         case TYPE_lng:
     811           0 :                                 NTILE_VALUE_SINGLE_IMP(lng);
     812           0 :                                 break;
     813             : #ifdef HAVE_HGE
     814           0 :                         case TYPE_hge:
     815           0 :                                 NTILE_VALUE_SINGLE_IMP(hge);
     816           0 :                                 break;
     817             : #endif
     818           0 :                         default:
     819           0 :                                 msg = createException(SQL, "sql.ntile", SQLSTATE(42000) "ntile not available for %s", ATOMname(tp2));
     820             :                 }
     821             :         }
     822             : 
     823          61 : bailout:
     824          61 :         unfix_inputs(3, b, p, n);
     825          61 :         finalize_output(res, r, msg);
     826          61 :         return MAL_SUCCEED;
     827             : }
     828             : 
     829             : static str
     830         368 : SQLanalytics_args(BAT **r, BAT **b, int *frame_type, BAT **p, BAT **o, BAT **s, BAT **e, Client cntxt, MalBlkPtr mb,
     831             :                                   MalStkPtr stk, InstrPtr pci, int rtype, const char *mod)
     832             : {
     833             :         (void) cntxt;
     834         368 :         if (pci->argc != 7)
     835           0 :                 throw(SQL, mod, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", mod);
     836             : 
     837         368 :         *frame_type = *getArgReference_int(stk, pci, 4);
     838         368 :         assert(*frame_type >= 0 && *frame_type <= 6);
     839             : 
     840         368 :         if (isaBatType(getArgType(mb, pci, 1)) && !(*b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))
     841           0 :                 throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor");
     842         368 :         if (*b && !(*r = COLnew((*b)->hseqbase, rtype ? rtype : (*b)->ttype, BATcount(*b), TRANSIENT)))
     843           0 :                 throw(MAL, mod, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     844         368 :         if (isaBatType(getArgType(mb, pci, 2)) && !(*p = BATdescriptor(*getArgReference_bat(stk, pci, 2))))
     845           0 :                 throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor");
     846         368 :         if ((*frame_type == 3 || *frame_type == 4) && isaBatType(getArgType(mb, pci, 3)) && !(*o = BATdescriptor(*getArgReference_bat(stk, pci, 3))))
     847           0 :                 throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor");
     848         368 :         if (*frame_type < 3 && isaBatType(getArgType(mb, pci, 5)) && !(*s = BATdescriptor(*getArgReference_bat(stk, pci, 5))))
     849           0 :                 throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor");
     850         368 :         if (*frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(*e = BATdescriptor(*getArgReference_bat(stk, pci, 6))))
     851           0 :                 throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor");
     852         368 :         if ((*s && BATcount(*b) != BATcount(*s)) || (*e && BATcount(*b) != BATcount(*e)) ||
     853         368 :                 (*p && BATcount(*b) != BATcount(*p)) || (*o && BATcount(*b) != BATcount(*o)))
     854           0 :                 throw(SQL, mod, ILLEGAL_ARGUMENT " Requires bats of identical size");
     855         368 :         if ((*p && (*p)->ttype != TYPE_bit) || (*o && (*o)->ttype != TYPE_bit) || (*s && (*s)->ttype != TYPE_oid) || (*e && (*e)->ttype != TYPE_oid))
     856           0 :                 throw(SQL, mod, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
     857             : 
     858             :         return MAL_SUCCEED;
     859             : }
     860             : 
     861             : static str
     862         183 : SQLanalytical_func(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
     863             :                                    gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int))
     864             : {
     865         183 :         int tpe = getArgType(mb, pci, 1), frame_type;
     866         183 :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
     867         183 :         str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, 0, op);
     868             :         bat *res = NULL;
     869             : 
     870         183 :         if (msg)
     871           0 :                 goto bailout;
     872         183 :         if (b) {
     873         173 :                 res = getArgReference_bat(stk, pci, 0);
     874             : 
     875         173 :                 if (func(r, p, o, b, s, e, getBatType(tpe), frame_type) != GDK_SUCCEED)
     876           0 :                         msg = createException(SQL, op, GDK_EXCEPTION);
     877             :         } else {
     878          10 :                 ValRecord *res = &(stk)->stk[(pci)->argv[0]];
     879          10 :                 ValRecord *in = &(stk)->stk[(pci)->argv[1]];
     880             : 
     881          10 :                 if (!VALcopy(res, in))
     882           0 :                         msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     883             :         }
     884             : 
     885          10 : bailout:
     886         183 :         unfix_inputs(5, b, p, o, s, e);
     887         183 :         finalize_output(res, r, msg);
     888         183 :         return msg;
     889             : }
     890             : 
     891             : static str
     892          63 : do_limit_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
     893             :                            gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, int))
     894             : {
     895          63 :         int tpe = getArgType(mb, pci, 1);
     896             :         BAT *r = NULL, *b = NULL, *s = NULL, *e = NULL; /* p and o are ignored for this one */
     897             :         bat *res = NULL;
     898             :         str msg = MAL_SUCCEED;
     899             : 
     900             :         (void) cntxt;
     901          63 :         if (pci->argc != 7)
     902           0 :                 throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", op);
     903             :         tpe = getArgType(mb, pci, 1);
     904             : 
     905          63 :         if (isaBatType(tpe))
     906          63 :                 tpe = getBatType(tpe);
     907          63 :         if (isaBatType(getArgType(mb, pci, 1))) {
     908          63 :                 res = getArgReference_bat(stk, pci, 0);
     909             : 
     910          63 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     911           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
     912           0 :                         goto bailout;
     913             :                 }
     914          63 :                 if (!(r = COLnew(b->hseqbase, b->ttype, BATcount(b), TRANSIENT))) {
     915           0 :                         msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     916           0 :                         goto bailout;
     917             :                 }
     918          63 :                 if (!(s = BATdescriptor(*getArgReference_bat(stk, pci, 5)))) {
     919           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
     920           0 :                         goto bailout;
     921             :                 }
     922          63 :                 if (!(e = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
     923           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
     924           0 :                         goto bailout;
     925             :                 }
     926          63 :                 if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e))) {
     927           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
     928           0 :                         goto bailout;
     929             :                 }
     930          63 :                 if ((s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
     931           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
     932           0 :                         goto bailout;
     933             :                 }
     934             : 
     935          63 :                 if (func(r, b, s, e, tpe) != GDK_SUCCEED)
     936           0 :                         msg = createException(SQL, op, GDK_EXCEPTION);
     937             :         } else {
     938           0 :                 ValRecord *res = &(stk)->stk[(pci)->argv[0]];
     939           0 :                 ValRecord *in = &(stk)->stk[(pci)->argv[1]];
     940             : 
     941           0 :                 if (!VALcopy(res, in))
     942           0 :                         msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     943             :         }
     944             : 
     945           0 : bailout:
     946          63 :         unfix_inputs(3, b, s, e);
     947          63 :         finalize_output(res, r, msg);
     948          63 :         return MAL_SUCCEED;
     949             : }
     950             : 
     951             : str
     952          32 : SQLfirst_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     953             : {
     954          32 :         return do_limit_value(cntxt, mb, stk, pci, "sql.first_value", GDKanalyticalfirst);
     955             : }
     956             : 
     957             : str
     958          31 : SQLlast_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     959             : {
     960          31 :         return do_limit_value(cntxt, mb, stk, pci, "sql.last_value", GDKanalyticallast);
     961             : }
     962             : 
     963             : #define NTH_VALUE_SINGLE_IMP(TPE) \
     964             :         do { \
     965             :                 TPE val = *(TPE*) VALget(nth); \
     966             :                 if (!VALisnil(nth) && val < 1) \
     967             :                         throw(SQL, "sql.nth_value", SQLSTATE(42000) "nth_value must be greater than zero"); \
     968             :                 if (VALisnil(nth) || val > 1) { \
     969             :                         ValRecord def = (ValRecord) {.vtype = TYPE_void,}; \
     970             :                         if (!VALinit(&def, tp1, ATOMnilptr(tp1)) || !VALcopy(res, &def)) { \
     971             :                                 VALclear(&def); \
     972             :                                 throw(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     973             :                         } \
     974             :                         VALclear(&def); \
     975             :                 } else { \
     976             :                         if (!VALcopy(res, in)) \
     977             :                                 throw(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     978             :                 } \
     979             :         } while(0)
     980             : 
     981             : str
     982          44 : SQLnth_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     983             : {
     984             :         BAT *r = NULL, *b = NULL, *l = NULL, *s = NULL, *e = NULL; /* p and o are ignored for this one */
     985             :         int tpe;
     986             :         bat *res = NULL;
     987             :         str msg = MAL_SUCCEED;
     988             :         bool is_a_bat;
     989             : 
     990             :         (void) cntxt;
     991          44 :         if (pci->argc != 8)
     992           0 :                 throw(SQL, "sql.nth_value", ILLEGAL_ARGUMENT "sql.nth_value requires exactly 8 arguments");
     993             : 
     994          44 :         tpe = getArgType(mb, pci, 1);
     995          44 :         is_a_bat = isaBatType(getArgType(mb, pci, 2));
     996             : 
     997          44 :         if (isaBatType(tpe)) {
     998             :                 lng *nth = NULL;
     999          40 :                 res = getArgReference_bat(stk, pci, 0);
    1000             : 
    1001          40 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1002           0 :                         msg = createException(SQL, "sql.nth_value", SQLSTATE(HY005) "Cannot access column descriptor");
    1003           0 :                         goto bailout;
    1004             :                 }
    1005          40 :                 tpe = getBatType(tpe);
    1006          40 :                 if (b && !(r = COLnew(b->hseqbase, tpe, BATcount(b), TRANSIENT))) {
    1007           0 :                         msg = createException(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1008           0 :                         goto bailout;
    1009             :                 }
    1010          40 :                 if (is_a_bat) {
    1011           5 :                         if (!(l = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
    1012           0 :                                 msg = createException(SQL, "sql.nth_value", SQLSTATE(HY005) "Cannot access column descriptor");
    1013           0 :                                 goto bailout;
    1014             :                         }
    1015             :                 } else {
    1016          35 :                         nth = getArgReference_lng(stk, pci, 2);
    1017             :                 }
    1018          40 :                 if (!(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
    1019           0 :                         msg = createException(SQL, "sql.nth_value", SQLSTATE(HY005) "Cannot access column descriptor");
    1020           0 :                         goto bailout;
    1021             :                 }
    1022          40 :                 if (!(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
    1023           0 :                         msg = createException(SQL, "sql.nth_value", SQLSTATE(HY005) "Cannot access column descriptor");
    1024           0 :                         goto bailout;
    1025             :                 }
    1026          40 :                 if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (l && BATcount(b) != BATcount(l))) {
    1027           0 :                         msg = createException(SQL, "sql.nth_value", ILLEGAL_ARGUMENT " Requires bats of identical size");
    1028           0 :                         goto bailout;
    1029             :                 }
    1030          40 :                 if ((s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
    1031           0 :                         msg = createException(SQL, "sql.nth_value", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
    1032           0 :                         goto bailout;
    1033             :                 }
    1034             : 
    1035          40 :                 if (GDKanalyticalnthvalue(r, b, s, e, l, nth, tpe) != GDK_SUCCEED)
    1036           0 :                         msg = createException(SQL, "sql.nth_value", GDK_EXCEPTION);
    1037             :         } else {
    1038           4 :                 ValRecord *res = &(stk)->stk[(pci)->argv[0]];
    1039           4 :                 ValRecord *in = &(stk)->stk[(pci)->argv[1]];
    1040             :                 lng nth = 0;
    1041             : 
    1042           4 :                 if (getArgType(mb, pci, 2) != TYPE_lng) {
    1043           0 :                         msg = createException(SQL, "sql.nth_value", SQLSTATE(42000) "nth_value offset not available for type %s", ATOMname(getArgType(mb, pci, 2)));
    1044           0 :                         goto bailout;
    1045             :                 }
    1046           4 :                 nth = *getArgReference_lng(stk, pci, 2);
    1047           4 :                 if (!is_lng_nil(nth) && nth < 1) {
    1048           0 :                         msg = createException(SQL, "sql.nth_value", SQLSTATE(42000) "nth_value must be greater than zero");
    1049           0 :                         goto bailout;
    1050             :                 }
    1051           4 :                 if (is_lng_nil(nth) || nth > 1) {
    1052           0 :                         ValRecord def = (ValRecord) {.vtype = TYPE_void,};
    1053           0 :                         if (!VALinit(&def, tpe, ATOMnilptr(tpe)) || !VALcopy(res, &def)) {
    1054           0 :                                 VALclear(&def);
    1055           0 :                                 msg = createException(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1056           0 :                                 goto bailout;
    1057             :                         }
    1058           0 :                         VALclear(&def);
    1059             :                 } else {
    1060           4 :                         if (!VALcopy(res, in))
    1061           0 :                                 msg = createException(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1062             :                 }
    1063             :         }
    1064             : 
    1065           4 : bailout:
    1066          44 :         unfix_inputs(4, b, l, s, e);
    1067          44 :         finalize_output(res, r, msg);
    1068          44 :         return msg;
    1069             : }
    1070             : 
    1071             : #define CHECK_L_VALUE(TPE) \
    1072             :         do { \
    1073             :                 TPE rval; \
    1074             :                 if (tp2_is_a_bat) { \
    1075             :                         if (!(l = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) { \
    1076             :                                 msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor"); \
    1077             :                                 goto bailout; \
    1078             :                         } \
    1079             :                         MT_lock_set(&l->theaplock); \
    1080             :                         rval = ((TPE*)Tloc(l, 0))[0]; \
    1081             :                         MT_lock_unset(&l->theaplock); \
    1082             :                 } else { \
    1083             :                         rval = *getArgReference_##TPE(stk, pci, 2); \
    1084             :                 } \
    1085             :                 if (!is_##TPE##_nil(rval) && rval < 0) { \
    1086             :                         gdk_call = dual; \
    1087             :                         rval *= -1; \
    1088             :                 } \
    1089             :                 l_value = is_##TPE##_nil(rval) ? BUN_NONE : (BUN)rval; \
    1090             :         } while(0)
    1091             : 
    1092             : static str
    1093          69 : do_lead_lag(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op, const char* desc,
    1094             :                         gdk_return (*func)(BAT *, BAT *, BAT *, BUN, const void* restrict, int),
    1095             :                         gdk_return (*dual)(BAT *, BAT *, BAT *, BUN, const void* restrict, int))
    1096             : {
    1097             :         int tp1, tp2, tp3, base = 2;
    1098             :         BUN l_value = 1;
    1099             :         const void *restrict default_value;
    1100             :         gdk_return (*gdk_call)(BAT *, BAT *, BAT *, BUN, const void* restrict, int) = func;
    1101             :         BAT *b = NULL, *l = NULL, *d = NULL, *p = NULL, *r = NULL;
    1102             :         bool tp2_is_a_bat;
    1103             :         str msg = MAL_SUCCEED;
    1104             :         bat *res = NULL;
    1105             : 
    1106             :         (void)cntxt;
    1107          69 :         if (pci->argc < 4 || pci->argc > 6)
    1108           0 :                 throw(SQL, op, SQLSTATE(42000) "%s called with invalid number of arguments", desc);
    1109             : 
    1110          69 :         tp1 = getArgType(mb, pci, 1);
    1111             : 
    1112          69 :         if (pci->argc > 4) { //contains (lag or lead) value;
    1113          28 :                 tp2 = getArgType(mb, pci, 2);
    1114          28 :                 tp2_is_a_bat = isaBatType(tp2);
    1115          28 :                 if (tp2_is_a_bat)
    1116           6 :                         tp2 = getBatType(tp2);
    1117             : 
    1118          28 :                 switch (tp2) {
    1119          28 :                         case TYPE_bte:
    1120          28 :                                 CHECK_L_VALUE(bte);
    1121             :                                 break;
    1122           0 :                         case TYPE_sht:
    1123           0 :                                 CHECK_L_VALUE(sht);
    1124             :                                 break;
    1125           0 :                         case TYPE_int:
    1126           0 :                                 CHECK_L_VALUE(int);
    1127             :                                 break;
    1128           0 :                         case TYPE_lng:
    1129           0 :                                 CHECK_L_VALUE(lng);
    1130             :                                 break;
    1131             : #ifdef HAVE_HGE
    1132           0 :                         case TYPE_hge:
    1133           0 :                                 CHECK_L_VALUE(hge);
    1134             :                                 break;
    1135             : #endif
    1136           0 :                         default:
    1137           0 :                                 throw(SQL, op, SQLSTATE(42000) "%s value not available for %s", desc, ATOMname(tp2));
    1138             :                 }
    1139             :                 base = 3;
    1140             :         }
    1141             : 
    1142          69 :         if (pci->argc > 5) { //contains default value;
    1143           9 :                 tp3 = getArgType(mb, pci, 3);
    1144          12 :                 if (isaBatType(tp3)) {
    1145             :                         BATiter bpi;
    1146             : 
    1147             :                         tp3 = getBatType(tp3);
    1148           3 :                         if (!(d = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
    1149           0 :                                 msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1150           0 :                                 goto bailout;
    1151             :                         }
    1152           3 :                         bpi = bat_iterator(d);
    1153           3 :                         default_value = BUNtail(bpi, 0);
    1154           3 :                         bat_iterator_end(&bpi);
    1155             :                 } else {
    1156           6 :                         ValRecord *in = &(stk)->stk[(pci)->argv[3]];
    1157           6 :                         default_value = VALget(in);
    1158             :                 }
    1159             :                 base = 4;
    1160             :         } else {
    1161             :                 int tpe = tp1;
    1162          60 :                 if (isaBatType(tpe))
    1163          54 :                         tpe = getBatType(tp1);
    1164          60 :                 default_value = ATOMnilptr(tpe);
    1165             :         }
    1166             : 
    1167          69 :         assert(default_value); //default value must be set
    1168             : 
    1169          69 :         if (isaBatType(tp1)) {
    1170          59 :                 res = getArgReference_bat(stk, pci, 0);
    1171          59 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1172           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1173           0 :                         goto bailout;
    1174             :                 }
    1175             : 
    1176          59 :                 tp1 = getBatType(tp1);
    1177          59 :                 if (!(r = COLnew(b->hseqbase, tp1, BATcount(b), TRANSIENT))) {
    1178           0 :                         msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1179           0 :                         goto bailout;
    1180             :                 }
    1181          59 :                 if (isaBatType(getArgType(mb, pci, base))) {
    1182          36 :                         if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, base)))) {
    1183           0 :                                 msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1184           0 :                                 goto bailout;
    1185             :                         }
    1186             :                 }
    1187          59 :                 if ((p && BATcount(b) != BATcount(p)) || (l && BATcount(b) != BATcount(l)) || (d && BATcount(b) != BATcount(d))) {
    1188           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1189           0 :                         goto bailout;
    1190             :                 }
    1191             : 
    1192          59 :                 if (gdk_call(r, b, p, l_value, default_value, tp1) != GDK_SUCCEED)
    1193           0 :                         msg = createException(SQL, op, GDK_EXCEPTION);
    1194             :         } else {
    1195          10 :                 ValRecord *res = &(stk)->stk[(pci)->argv[0]];
    1196          10 :                 ValRecord *in = &(stk)->stk[(pci)->argv[1]];
    1197             : 
    1198          10 :                 if (l_value == 0) {
    1199           4 :                         if (!VALcopy(res, in))
    1200           0 :                                 msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1201             :                 } else {
    1202           6 :                         ValRecord def = (ValRecord) {.vtype = TYPE_void,};
    1203             : 
    1204           6 :                         if (!VALinit(&def, tp1, default_value) || !VALcopy(res, &def))
    1205           0 :                                 msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1206           6 :                         VALclear(&def);
    1207             :                 }
    1208             :         }
    1209             : 
    1210          69 : bailout:
    1211          69 :         unfix_inputs(4, b, p, l, d);
    1212          69 :         finalize_output(res, r, msg);
    1213          69 :         return msg;
    1214             : }
    1215             : 
    1216             : str
    1217          35 : SQLlag(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1218             : {
    1219          35 :         return do_lead_lag(cntxt, mb, stk, pci, "sql.lag", "lag", GDKanalyticallag, GDKanalyticallead);
    1220             : }
    1221             : 
    1222             : str
    1223          34 : SQLlead(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1224             : {
    1225          34 :         return do_lead_lag(cntxt, mb, stk, pci, "sql.lead", "lead", GDKanalyticallead, GDKanalyticallag);
    1226             : }
    1227             : 
    1228             : str
    1229          70 : SQLmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1230             : {
    1231          70 :         return SQLanalytical_func(cntxt, mb, stk, pci, "sql.min", GDKanalyticalmin);
    1232             : }
    1233             : 
    1234             : str
    1235         113 : SQLmax(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1236             : {
    1237         113 :         return SQLanalytical_func(cntxt, mb, stk, pci, "sql.max", GDKanalyticalmax);
    1238             : }
    1239             : 
    1240             : str
    1241         501 : SQLbasecount(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1242             : {
    1243         501 :         lng *res = getArgReference_lng(stk, pci, 0);
    1244         501 :         str sname = *getArgReference_str(stk, pci, 1);
    1245         501 :         str tname = *getArgReference_str(stk, pci, 2);
    1246         501 :         mvc *m = NULL;
    1247             :         str msg;
    1248             :         sql_schema *s = NULL;
    1249             :         sql_table *t = NULL;
    1250             :         sql_column *c = NULL;
    1251             : 
    1252         501 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
    1253             :                 return msg;
    1254         501 :         if ((msg = checkSQLContext(cntxt)) != NULL)
    1255             :                 return msg;
    1256         501 :         if (!(s = mvc_bind_schema(m, sname)))
    1257           0 :                 throw(SQL, "sql.count", SQLSTATE(3F000) "Schema missing %s", sname);
    1258         501 :         if (!(t = mvc_bind_table(m, s, tname)))
    1259           0 :                 throw(SQL, "sql.count", SQLSTATE(42S02) "Table missing %s.%s",sname,tname);
    1260         501 :         if (!isTable(t))
    1261           0 :                 throw(SQL, "sql.count", SQLSTATE(42000) "%s '%s' is not persistent",
    1262           0 :                           TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
    1263         501 :         if (!ol_first_node(t->columns))
    1264           0 :                 throw(SQL, "sql.count", SQLSTATE(42S22) "Column missing %s.%s",sname,tname);
    1265         501 :         c = ol_first_node(t->columns)->data;
    1266         501 :         sqlstore *store = m->session->tr->store;
    1267             : 
    1268         501 :         *res = store->storage_api.count_col(m->session->tr, c, 10);
    1269         501 :         return msg;
    1270             : }
    1271             : 
    1272             : str
    1273         170 : SQLcount(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1274             : {
    1275             :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
    1276             :         int tpe, frame_type;
    1277             :         bit ignore_nils;
    1278             :         bat *res = NULL;
    1279             :         str msg = MAL_SUCCEED;
    1280             : 
    1281             :         (void) cntxt;
    1282         170 :         if (pci->argc != 8)
    1283           0 :                 throw(SQL, "sql.count", ILLEGAL_ARGUMENT "sql.count requires exactly 8 arguments");
    1284         170 :         tpe = getArgType(mb, pci, 1);
    1285         170 :         ignore_nils = *getArgReference_bit(stk, pci, 2);
    1286         170 :         frame_type = *getArgReference_int(stk, pci, 5);
    1287         170 :         assert(frame_type >= 0 && frame_type <= 6);
    1288             : 
    1289         170 :         if (isaBatType(tpe))
    1290         159 :                 tpe = getBatType(tpe);
    1291         170 :         if (isaBatType(getArgType(mb, pci, 1)) && (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
    1292           0 :                 msg = createException(SQL, "sql.count", SQLSTATE(HY005) "Cannot access column descriptor");
    1293           0 :                 goto bailout;
    1294             :         }
    1295         159 :         if (b && !(r = COLnew(b->hseqbase, TYPE_lng, BATcount(b), TRANSIENT))) {
    1296           0 :                 msg = createException(SQL, "sql.count", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1297           0 :                 goto bailout;
    1298             :         }
    1299         170 :         if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
    1300           0 :                 msg = createException(SQL, "sql.count", SQLSTATE(HY005) "Cannot access column descriptor");
    1301           0 :                 goto bailout;
    1302             :         }
    1303         170 :         if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 4)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 4)))) {
    1304           0 :                 msg = createException(SQL, "sql.count", SQLSTATE(HY005) "Cannot access column descriptor");
    1305           0 :                 goto bailout;
    1306             :         }
    1307         170 :         if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
    1308           0 :                 msg = createException(SQL, "sql.count", SQLSTATE(HY005) "Cannot access column descriptor");
    1309           0 :                 goto bailout;
    1310             :         }
    1311         170 :         if (frame_type < 3 && isaBatType(getArgType(mb, pci, 7)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
    1312           0 :                 msg = createException(SQL, "sql.count", SQLSTATE(HY005) "Cannot access column descriptor");
    1313           0 :                 goto bailout;
    1314             :         }
    1315         170 :         if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o))) {
    1316           0 :                 msg = createException(SQL, "sql.count", ILLEGAL_ARGUMENT " Requires bats of identical size");
    1317           0 :                 goto bailout;
    1318             :         }
    1319         170 :         if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
    1320           0 :                 msg = createException(SQL, "sql.count", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
    1321           0 :                 goto bailout;
    1322             :         }
    1323             : 
    1324         170 :         if (b) {
    1325         159 :                 res = getArgReference_bat(stk, pci, 0);
    1326             : 
    1327         159 :                 if (GDKanalyticalcount(r, p, o, b, s, e, ignore_nils, tpe, frame_type) != GDK_SUCCEED)
    1328           0 :                         msg = createException(SQL, "sql.count", GDK_EXCEPTION);
    1329             :         } else {
    1330          11 :                 lng *res = getArgReference_lng(stk, pci, 0);
    1331          11 :                 ValRecord *in = &(stk)->stk[(pci)->argv[1]];
    1332             : 
    1333          11 :                 *res = (VALisnil(in) && ignore_nils) ? 0 : 1;
    1334             :         }
    1335             : 
    1336         170 : bailout:
    1337         170 :         unfix_inputs(5, b, p, o, s, e);
    1338         170 :         finalize_output(res, r, msg);
    1339         170 :         return msg;
    1340             : }
    1341             : 
    1342             : static str
    1343         153 : do_analytical_sumprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
    1344             :                                           gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int, int))
    1345             : {
    1346             :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
    1347             :         int tp1, tp2, frame_type;
    1348             :         str msg = MAL_SUCCEED;
    1349             :         bat *res = NULL;
    1350             : 
    1351             :         (void) cntxt;
    1352         153 :         if (pci->argc != 7)
    1353           0 :                 throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", op);
    1354         153 :         tp1 = getArgType(mb, pci, 1);
    1355         153 :         frame_type = *getArgReference_int(stk, pci, 4);
    1356         153 :         assert(frame_type >= 0 && frame_type <= 6);
    1357             : 
    1358         153 :         if (isaBatType(tp1)) {
    1359         146 :                 tp1 = getBatType(tp1);
    1360         146 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1361           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1362           0 :                         goto bailout;
    1363             :                 }
    1364             :         }
    1365         153 :         switch (tp1) {
    1366             :                 case TYPE_bte:
    1367             :                 case TYPE_sht:
    1368             :                 case TYPE_int:
    1369             :                 case TYPE_lng:
    1370             : #ifdef HAVE_HGE
    1371             :                 case TYPE_hge:
    1372             :                         tp2 = TYPE_hge;
    1373             : #else
    1374             :                         tp2 = TYPE_lng;
    1375             : #endif
    1376             :                         break;
    1377          20 :                 case TYPE_flt:
    1378             :                         tp2 = TYPE_flt;
    1379          20 :                         break;
    1380          11 :                 case TYPE_dbl:
    1381             :                         tp2 = TYPE_dbl;
    1382          11 :                         break;
    1383           0 :                 default: {
    1384           0 :                         msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1));
    1385           0 :                         goto bailout;
    1386             :                 }
    1387             :         }
    1388         153 :         if (b) {
    1389         146 :                 res = getArgReference_bat(stk, pci, 0);
    1390         146 :                 if (!(r = COLnew(b->hseqbase, tp2, BATcount(b), TRANSIENT))) {
    1391           0 :                         msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1392           0 :                         goto bailout;
    1393             :                 }
    1394         146 :                 if (isaBatType(getArgType(mb, pci, 2)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
    1395           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1396           0 :                         goto bailout;
    1397             :                 }
    1398         146 :                 if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 3)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
    1399           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1400           0 :                         goto bailout;
    1401             :                 }
    1402         146 :                 if (frame_type < 3 && isaBatType(getArgType(mb, pci, 5)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 5)))) {
    1403           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1404           0 :                         goto bailout;
    1405             :                 }
    1406         146 :                 if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
    1407           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1408           0 :                         goto bailout;
    1409             :                 }
    1410         146 :                 if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o))) {
    1411           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1412           0 :                         goto bailout;
    1413             :                 }
    1414         146 :                 if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
    1415           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
    1416           0 :                         goto bailout;
    1417             :                 }
    1418             : 
    1419         146 :                 if (func(r, p, o, b, s, e, tp1, tp2, frame_type) != GDK_SUCCEED)
    1420           0 :                         msg = createException(SQL, op, GDK_EXCEPTION);
    1421             :         } else {
    1422             :                 /* the pointers here will always point from bte to dbl, so no strings are handled here */
    1423           7 :                 ptr res = getArgReference(stk, pci, 0);
    1424           7 :                 ptr in = getArgReference(stk, pci, 1);
    1425           7 :                 int scale = 0;
    1426             : 
    1427           7 :                 switch (tp1) {
    1428             : #ifdef HAVE_HGE
    1429           2 :                         case TYPE_bte:
    1430           2 :                                 msg = bte_dec2_hge((hge*)res, &scale, (bte*)in);
    1431           2 :                                 break;
    1432           0 :                         case TYPE_sht:
    1433           0 :                                 msg = sht_dec2_hge((hge*)res, &scale, (sht*)in);
    1434           0 :                                 break;
    1435           0 :                         case TYPE_int:
    1436           0 :                                 msg = int_dec2_hge((hge*)res, &scale, (int*)in);
    1437           0 :                                 break;
    1438           0 :                         case TYPE_lng:
    1439           0 :                                 msg = lng_dec2_hge((hge*)res, &scale, (lng*)in);
    1440           0 :                                 break;
    1441           3 :                         case TYPE_hge:
    1442           3 :                                 *(hge*)res = *((hge*)in);
    1443           3 :                                 break;
    1444             : #else
    1445             :                         case TYPE_bte:
    1446             :                                 msg = bte_dec2_lng((lng*)res, &scale, (bte*)in);
    1447             :                                 break;
    1448             :                         case TYPE_sht:
    1449             :                                 msg = sht_dec2_lng((lng*)res, &scale, (sht*)in);
    1450             :                                 break;
    1451             :                         case TYPE_int:
    1452             :                                 msg = int_dec2_lng((lng*)res, &scale, (int*)in);
    1453             :                                 break;
    1454             :                         case TYPE_lng:
    1455             :                                 *(lng*)res = *((lng*)in);
    1456             :                                 break;
    1457             : #endif
    1458           0 :                         case TYPE_flt: {
    1459           0 :                                 flt fp = *((flt*)in);
    1460           0 :                                 *(dbl*)res = is_flt_nil(fp) ? dbl_nil : (dbl) fp;
    1461           0 :                         } break;
    1462           2 :                         case TYPE_dbl:
    1463           2 :                                 *(dbl*)res = *((dbl*)in);
    1464           2 :                                 break;
    1465           0 :                         default:
    1466           0 :                                 msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1));
    1467             :                 }
    1468             :         }
    1469             : 
    1470         153 : bailout:
    1471         153 :         unfix_inputs(5, b, p, o, s, e);
    1472         153 :         finalize_output(res, r, msg);
    1473         153 :         return msg;
    1474             : }
    1475             : 
    1476             : str
    1477         122 : SQLsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1478             : {
    1479         122 :         return do_analytical_sumprod(cntxt, mb, stk, pci, "sql.sum", GDKanalyticalsum);
    1480             : }
    1481             : 
    1482             : str
    1483          31 : SQLprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1484             : {
    1485          31 :         return do_analytical_sumprod(cntxt, mb, stk, pci, "sql.prod", GDKanalyticalprod);
    1486             : }
    1487             : 
    1488             : str
    1489          83 : SQLavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1490             : {
    1491          83 :         int tpe = getArgType(mb, pci, 1), frame_type;
    1492          83 :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
    1493          83 :         str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, TYPE_dbl, "sql.avg");
    1494             :         bat *res = NULL;
    1495             : 
    1496          83 :         if (msg)
    1497           0 :                 goto bailout;
    1498          83 :         if (isaBatType(tpe))
    1499          70 :                 tpe = getBatType(tpe);
    1500             : 
    1501          83 :         if (b) {
    1502          70 :                 res = getArgReference_bat(stk, pci, 0);
    1503             : 
    1504          70 :                 if (GDKanalyticalavg(r, p, o, b, s, e, tpe, frame_type) != GDK_SUCCEED)
    1505           0 :                         msg = createException(SQL, "sql.avg", GDK_EXCEPTION);
    1506             :         } else {
    1507             :                 /* the pointers here will always point from bte to dbl, so no strings are handled here */
    1508          13 :                 ptr res = getArgReference(stk, pci, 0);
    1509          13 :                 ptr in = getArgReference(stk, pci, 1);
    1510          13 :                 int scale = 0;
    1511             : 
    1512          13 :                 switch (tpe) {
    1513           2 :                         case TYPE_bte:
    1514           2 :                                 msg = bte_dec2_dbl((dbl*)res, &scale, (bte*)in);
    1515           2 :                                 break;
    1516           0 :                         case TYPE_sht:
    1517           0 :                                 msg = sht_dec2_dbl((dbl*)res, &scale, (sht*)in);
    1518           0 :                                 break;
    1519           0 :                         case TYPE_int:
    1520           0 :                                 msg = int_dec2_dbl((dbl*)res, &scale, (int*)in);
    1521           0 :                                 break;
    1522           0 :                         case TYPE_lng:
    1523           0 :                                 msg = lng_dec2_dbl((dbl*)res, &scale, (lng*)in);
    1524           0 :                                 break;
    1525             : #ifdef HAVE_HGE
    1526           8 :                         case TYPE_hge:
    1527           8 :                                 msg = hge_dec2_dbl((dbl*)res, &scale, (hge*)in);
    1528           8 :                                 break;
    1529             : #endif
    1530           0 :                         case TYPE_flt: {
    1531           0 :                                 flt fp = *((flt*)in);
    1532           0 :                                 *(dbl*)res = is_flt_nil(fp) ? dbl_nil : (dbl) fp;
    1533           0 :                         } break;
    1534           3 :                         case TYPE_dbl:
    1535           3 :                                 *(dbl*)res = *((dbl*)in);
    1536           3 :                                 break;
    1537           0 :                         default:
    1538           0 :                                 msg = createException(SQL, "sql.avg", SQLSTATE(42000) "sql.avg not available for %s to dbl", ATOMname(tpe));
    1539             :                 }
    1540             :         }
    1541             : 
    1542          83 : bailout:
    1543          83 :         unfix_inputs(5, b, p, o, s, e);
    1544          83 :         finalize_output(res, r, msg);
    1545          83 :         return msg;
    1546             : }
    1547             : 
    1548             : str
    1549          48 : SQLavginteger(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1550             : {
    1551          48 :         int tpe = getArgType(mb, pci, 1), frame_type;
    1552          48 :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
    1553          48 :         str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, 0, "sql.avg");
    1554             :         bat *res = NULL;
    1555             : 
    1556          48 :         if (msg)
    1557           0 :                 goto bailout;
    1558          48 :         if (isaBatType(tpe))
    1559          48 :                 tpe = getBatType(tpe);
    1560             : 
    1561          48 :         if (b) {
    1562          48 :                 res = getArgReference_bat(stk, pci, 0);
    1563             : 
    1564          48 :                 if (GDKanalyticalavginteger(r, p, o, b, s, e, tpe, frame_type) != GDK_SUCCEED)
    1565           0 :                         msg = createException(SQL, "sql.avg", GDK_EXCEPTION);
    1566             :         } else {
    1567           0 :                 ValRecord *res = &(stk)->stk[(pci)->argv[0]];
    1568           0 :                 ValRecord *in = &(stk)->stk[(pci)->argv[1]];
    1569             : 
    1570           0 :                 switch (tpe) {
    1571           0 :                         case TYPE_bte:
    1572             :                         case TYPE_sht:
    1573             :                         case TYPE_int:
    1574             :                         case TYPE_lng:
    1575             : #ifdef HAVE_HGE
    1576             :                         case TYPE_hge:
    1577             : #endif
    1578           0 :                                 if (!VALcopy(res, in))
    1579           0 :                                         msg = createException(SQL, "sql.avg", SQLSTATE(HY013) MAL_MALLOC_FAIL); /* malloc failure should never happen, but let it be here */
    1580             :                                 break;
    1581           0 :                         default:
    1582           0 :                                 msg = createException(SQL, "sql.avg", SQLSTATE(42000) "sql.avg not available for %s to %s", ATOMname(tpe), ATOMname(tpe));
    1583             :                 }
    1584             :         }
    1585             : 
    1586          48 : bailout:
    1587          48 :         unfix_inputs(5, b, p, o, s, e);
    1588          48 :         finalize_output(res, r, msg);
    1589          48 :         return msg;
    1590             : }
    1591             : 
    1592             : static str
    1593          54 : do_stddev_and_variance(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
    1594             :                                            gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int))
    1595             : {
    1596          54 :         int tpe = getArgType(mb, pci, 1), frame_type;
    1597          54 :         BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
    1598          54 :         str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, TYPE_dbl, op);
    1599             :         bat *res = NULL;
    1600             : 
    1601          54 :         if (msg)
    1602           0 :                 goto bailout;
    1603          54 :         if (isaBatType(tpe))
    1604          54 :                 tpe = getBatType(tpe);
    1605             : 
    1606          54 :         if (b) {
    1607          54 :                 res = getArgReference_bat(stk, pci, 0);
    1608             : 
    1609          54 :                 if (func(r, p, o, b, s, e, tpe, frame_type) != GDK_SUCCEED)
    1610           2 :                         msg = createException(SQL, op, GDK_EXCEPTION);
    1611             :         } else {
    1612           0 :                 dbl *res = getArgReference_dbl(stk, pci, 0);
    1613           0 :                 ValRecord *input1 = &(stk)->stk[(pci)->argv[1]];
    1614             : 
    1615           0 :                 switch (tpe) {
    1616           0 :                         case TYPE_bte:
    1617             :                         case TYPE_sht:
    1618             :                         case TYPE_int:
    1619             :                         case TYPE_lng:
    1620             : #ifdef HAVE_HGE
    1621             :                         case TYPE_hge:
    1622             : #endif
    1623             :                         case TYPE_flt:
    1624             :                         case TYPE_dbl:
    1625           0 :                                 *res = VALisnil(input1) ? dbl_nil : 0;
    1626           0 :                                 break;
    1627           0 :                         default:
    1628           0 :                                 msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tpe));
    1629             :                 }
    1630             :         }
    1631             : 
    1632          54 : bailout:
    1633          54 :         unfix_inputs(5, b, p, o, s, e);
    1634          54 :         finalize_output(res, r, msg);
    1635          54 :         return msg;
    1636             : }
    1637             : 
    1638             : str
    1639          17 : SQLstddev_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1640             : {
    1641          17 :         return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.stdev", GDKanalytical_stddev_samp);
    1642             : }
    1643             : 
    1644             : str
    1645          10 : SQLstddev_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1646             : {
    1647          10 :         return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.stdevp", GDKanalytical_stddev_pop);
    1648             : }
    1649             : 
    1650             : str
    1651          11 : SQLvar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1652             : {
    1653          11 :         return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.variance", GDKanalytical_variance_samp);
    1654             : }
    1655             : 
    1656             : str
    1657          16 : SQLvar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1658             : {
    1659          16 :         return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.variancep", GDKanalytical_variance_pop);
    1660             : }
    1661             : 
    1662             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_UNBOUNDED_TILL_CURRENT_ROW(TPE) \
    1663             :         do { \
    1664             :                 TPE *restrict bp = (TPE*)di.base; \
    1665             :                 for (; k < i;) { \
    1666             :                         j = k; \
    1667             :                         do {    \
    1668             :                                 n += !is_##TPE##_nil(bp[k]);    \
    1669             :                                 k++; \
    1670             :                         } while (k < i && !opp[k]);  \
    1671             :                         if (n > minimum) { /* covariance_samp requires at least one value */ \
    1672             :                                 rr = val; \
    1673             :                         } else { \
    1674             :                                 rr = dbl_nil; \
    1675             :                                 has_nils = true; \
    1676             :                         } \
    1677             :                         for (; j < k; j++) \
    1678             :                                 rb[j] = rr; \
    1679             :                 } \
    1680             :                 n = 0;  \
    1681             :                 k = i; \
    1682             :         } while (0)
    1683             : 
    1684             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_CURRENT_ROW_TILL_UNBOUNDED(TPE) \
    1685             :         do { \
    1686             :                 TPE *restrict bp = (TPE*)di.base; \
    1687             :                 l = i - 1; \
    1688             :                 for (j = l; ; j--) { \
    1689             :                         n += !is_##TPE##_nil(bp[j]);    \
    1690             :                         if (opp[j] || j == k) { \
    1691             :                                 if (n > minimum) { /* covariance_samp requires at least one value */ \
    1692             :                                         rr = val; \
    1693             :                                 } else { \
    1694             :                                         rr = dbl_nil; \
    1695             :                                         has_nils = true; \
    1696             :                                 } \
    1697             :                                 for (; ; l--) { \
    1698             :                                         rb[l] = rr; \
    1699             :                                         if (l == j)     \
    1700             :                                                 break;  \
    1701             :                                 } \
    1702             :                                 if (j == k)     \
    1703             :                                         break;  \
    1704             :                                 l = j - 1;      \
    1705             :                         }       \
    1706             :                 }       \
    1707             :                 n = 0;  \
    1708             :                 k = i; \
    1709             :         } while (0)
    1710             : 
    1711             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_ALL_ROWS(TPE) \
    1712             :         do { \
    1713             :                 TPE *restrict bp = (TPE*)di.base; \
    1714             :                 for (; j < i; j++) \
    1715             :                         n += !is_##TPE##_nil(bp[j]);    \
    1716             :                 if (n > minimum) { /* covariance_samp requires at least one value */ \
    1717             :                         rr = val; \
    1718             :                 } else { \
    1719             :                         rr = dbl_nil; \
    1720             :                         has_nils = true; \
    1721             :                 } \
    1722             :                 for (; k < i; k++) \
    1723             :                         rb[k] = rr;     \
    1724             :                 n = 0; \
    1725             :         } while (0)
    1726             : 
    1727             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_CURRENT_ROW(TPE) \
    1728             :         do { \
    1729             :                 TPE *restrict bp = (TPE*)di.base; \
    1730             :                 for (; k < i; k++) { \
    1731             :                         n += !is_##TPE##_nil(bp[k]);    \
    1732             :                         if (n > minimum) { /* covariance_samp requires at least one value */ \
    1733             :                                 rb[k] = val; \
    1734             :                         } else { \
    1735             :                                 rb[k] = dbl_nil; \
    1736             :                                 has_nils = true; \
    1737             :                         } \
    1738             :                         n = 0; \
    1739             :                 }       \
    1740             :         } while (0)
    1741             : 
    1742             : #define INIT_AGGREGATE_COUNT(TPE, NOTHING1, NOTHING2) \
    1743             :         do { \
    1744             :                 computed = 0; \
    1745             :         } while (0)
    1746             : #define COMPUTE_LEVEL0_COUNT_FIXED(X, TPE, NOTHING1, NOTHING2) \
    1747             :         do { \
    1748             :                 computed = !is_##TPE##_nil(bp[j + X]); \
    1749             :         } while (0)
    1750             : #define COMPUTE_LEVELN_COUNT(VAL, NOTHING1, NOTHING2, NOTHING3) \
    1751             :         do { \
    1752             :                 computed += VAL; \
    1753             :         } while (0)
    1754             : #define FINALIZE_AGGREGATE_COUNT(NOTHING1, NOTHING2, NOTHING3) \
    1755             :         do { \
    1756             :                 if (computed > minimum) { /* covariance_samp requires at least one value */ \
    1757             :                         rb[k] = val; \
    1758             :                 } else { \
    1759             :                         rb[k] = dbl_nil; \
    1760             :                         has_nils = true; \
    1761             :                 } \
    1762             :         } while (0)
    1763             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_OTHERS(TPE) \
    1764             :         do { \
    1765             :                 TPE *restrict bp = (TPE*)di.base; \
    1766             :                 oid ncount = i - k; \
    1767             :                 if (GDKrebuild_segment_tree(ncount, sizeof(lng), st, &segment_tree, &levels_offset, &nlevels) != GDK_SUCCEED) { \
    1768             :                         msg = createException(SQL, op, GDK_EXCEPTION); \
    1769             :                         goto bailout; \
    1770             :                 } \
    1771             :                 populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_FIXED, COMPUTE_LEVELN_COUNT, TPE, NOTHING, NOTHING); \
    1772             :                 for (; k < i; k++) \
    1773             :                         compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, TPE, NOTHING, NOTHING); \
    1774             :                 j = k; \
    1775             :         } while (0)
    1776             : 
    1777             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(TPE, IMP)                \
    1778             :         do {                                            \
    1779             :                 if (p) {                                        \
    1780             :                         for (; i < cnt; i++) {               \
    1781             :                                 if (np[i])      {               \
    1782             : covariance##TPE##IMP: \
    1783             :                                         IMP(TPE);       \
    1784             :                                 } \
    1785             :                         }                                               \
    1786             :                 }       \
    1787             :                 if (!last) { /* hack to reduce code explosion, there's no need to duplicate the code to iterate each partition */ \
    1788             :                         last = true; \
    1789             :                         i = cnt; \
    1790             :                         goto covariance##TPE##IMP; \
    1791             :                 } \
    1792             :         } while (0)
    1793             : 
    1794             : #ifdef HAVE_HGE
    1795             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP) \
    1796             :         case TYPE_hge: \
    1797             :                 COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(hge, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1798             :         break;
    1799             : #else
    1800             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP)
    1801             : #endif
    1802             : 
    1803             : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(IMP)               \
    1804             :         do { \
    1805             :                 switch (tp1) {  \
    1806             :                 case TYPE_bte:  \
    1807             :                         COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(bte, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1808             :                         break;  \
    1809             :                 case TYPE_sht:  \
    1810             :                         COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(sht, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1811             :                         break;  \
    1812             :                 case TYPE_int:  \
    1813             :                         COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(int, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1814             :                         break;  \
    1815             :                 case TYPE_lng:  \
    1816             :                         COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(lng, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1817             :                         break;  \
    1818             :                 case TYPE_flt:  \
    1819             :                         COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(flt, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1820             :                         break;  \
    1821             :                 case TYPE_dbl:  \
    1822             :                         COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(dbl, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
    1823             :                         break;  \
    1824             :                 COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP)  \
    1825             :                 default: {      \
    1826             :                         msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1)); \
    1827             :                         goto bailout; \
    1828             :                 } \
    1829             :                 }       \
    1830             :         } while (0)
    1831             : 
    1832             : static str
    1833         146 : do_covariance_and_correlation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
    1834             :                                                           gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int), lng minimum, dbl defaultv, dbl single_case)
    1835             : {
    1836             :         BAT *r = NULL, *b = NULL, *c = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL, *st = NULL;
    1837             :         int tp1, tp2, frame_type;
    1838             :         bool is_a_bat1, is_a_bat2;
    1839             :         str msg = MAL_SUCCEED;
    1840             :         bat *res = NULL;
    1841         146 :         void *segment_tree = NULL;
    1842         146 :         oid *levels_offset = NULL;
    1843             : 
    1844             :         (void)cntxt;
    1845         146 :         if (pci->argc != 8)
    1846           0 :                 throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 8 arguments", op);
    1847             : 
    1848         146 :         tp1 = getArgType(mb, pci, 1);
    1849         146 :         tp2 = getArgType(mb, pci, 2);
    1850         146 :         frame_type = *getArgReference_int(stk, pci, 5);
    1851         146 :         assert(frame_type >= 0 && frame_type <= 6);
    1852         146 :         is_a_bat1 = isaBatType(tp1);
    1853         146 :         is_a_bat2 = isaBatType(tp2);
    1854             : 
    1855         146 :         if (is_a_bat1)
    1856         139 :                 tp1 = getBatType(tp1);
    1857         146 :         if (is_a_bat2)
    1858         117 :                 tp2 = getBatType(tp2);
    1859         146 :         if (tp1 != tp2)
    1860           0 :                 throw(SQL, op, SQLSTATE(42000) "The input arguments for %s must be from the same type", op);
    1861             : 
    1862         146 :         if (is_a_bat1 || is_a_bat2) {
    1863         139 :                 res = getArgReference_bat(stk, pci, 0);
    1864             : 
    1865         139 :                 if (is_a_bat1 && !(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1866           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1867           0 :                         goto bailout;
    1868             :                 }
    1869         139 :                 if (is_a_bat2 && !(c = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
    1870           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1871           0 :                         goto bailout;
    1872             :                 }
    1873         138 :                 if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
    1874           0 :                         msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1875           0 :                         goto bailout;
    1876             :                 }
    1877         139 :                 if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
    1878           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1879           0 :                         goto bailout;
    1880             :                 }
    1881         139 :                 if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 4)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 4)))) {
    1882           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1883           0 :                         goto bailout;
    1884             :                 }
    1885         139 :                 if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
    1886           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1887           0 :                         goto bailout;
    1888             :                 }
    1889         139 :                 if (frame_type < 3 && isaBatType(getArgType(mb, pci, 7)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
    1890           0 :                         msg = createException(SQL, op, SQLSTATE(HY005) "Cannot access column descriptor");
    1891           0 :                         goto bailout;
    1892             :                 }
    1893         139 :                 if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o)) || (c && BATcount(b) != BATcount(c))) {
    1894           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
    1895           0 :                         goto bailout;
    1896             :                 }
    1897         139 :                 if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
    1898           0 :                         msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
    1899           0 :                         goto bailout;
    1900             :                 }
    1901             : 
    1902         139 :                 if (is_a_bat1 && is_a_bat2) {
    1903         117 :                         if (func(r, p, o, b, c, s, e, tp1, frame_type) != GDK_SUCCEED)
    1904           2 :                                 msg = createException(SQL, op, GDK_EXCEPTION);
    1905             :                 } else {
    1906             :                         /* corner case, second column is a constant, calculate it this way... */
    1907             :                         BAT *d = b ? b : c;
    1908          22 :                         BATiter di = bat_iterator(d);
    1909          22 :                         ValRecord *input2 = &(stk)->stk[(pci)->argv[b ? 2 : 1]];
    1910          22 :                         BATiter si = bat_iterator(s);
    1911          22 :                         BATiter ei = bat_iterator(e);
    1912          22 :                         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(d), *restrict start = s ? (oid*)si.base : NULL, *restrict end = e ? (oid*)ei.base : NULL,
    1913          22 :                                 nlevels = 0;
    1914             :                         lng n = 0;
    1915          22 :                         BATiter pi = bat_iterator(p);
    1916          22 :                         BATiter oi = bat_iterator(o);
    1917          22 :                         bit *np = pi.base, *opp = oi.base;
    1918          22 :                         dbl *restrict rb = (dbl *) Tloc(r, 0), val = VALisnil(input2) ? dbl_nil : defaultv, rr;
    1919          22 :                         bool has_nils = is_dbl_nil(val), last = false;
    1920             : 
    1921          22 :                         if (cnt > 0) {
    1922          22 :                                 switch (frame_type) {
    1923           6 :                                 case 3: /* unbounded until current row */       {
    1924         172 :                                         COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
    1925             :                                 } break;
    1926           0 :                                 case 4: /* current row until unbounded */       {
    1927           0 :                                         COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
    1928             :                                 } break;
    1929          12 :                                 case 5: /* all rows */  {
    1930         266 :                                         COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(ALL_ROWS);
    1931             :                                 } break;
    1932           0 :                                 case 6: /* current row */ {
    1933           0 :                                         COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(CURRENT_ROW);
    1934             :                                 } break;
    1935           4 :                                 default: {
    1936           4 :                                         if ((st = GDKinitialize_segment_tree())) {
    1937         388 :                                                 COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(OTHERS);
    1938             :                                         } else {
    1939           0 :                                                 msg = createException(SQL, op, GDK_EXCEPTION);
    1940             :                                         }
    1941             :                                 }
    1942             :                                 }
    1943             :                         }
    1944          22 :                         bat_iterator_end(&di);
    1945          22 :                         bat_iterator_end(&ei);
    1946          22 :                         bat_iterator_end(&si);
    1947          22 :                         bat_iterator_end(&oi);
    1948          22 :                         bat_iterator_end(&pi);
    1949             : 
    1950          22 :                         BATsetcount(r, cnt);
    1951          22 :                         r->tnonil = !has_nils;
    1952          22 :                         r->tnil = has_nils;
    1953             :                 }
    1954             :         } else {
    1955           7 :                 dbl *res = getArgReference_dbl(stk, pci, 0);
    1956           7 :                 ValRecord *input1 = &(stk)->stk[(pci)->argv[1]];
    1957           7 :                 ValRecord *input2 = &(stk)->stk[(pci)->argv[2]];
    1958             : 
    1959           7 :                 switch (tp1) {
    1960           7 :                         case TYPE_bte:
    1961             :                         case TYPE_sht:
    1962             :                         case TYPE_int:
    1963             :                         case TYPE_lng:
    1964             : #ifdef HAVE_HGE
    1965             :                         case TYPE_hge:
    1966             : #endif
    1967             :                         case TYPE_flt:
    1968             :                         case TYPE_dbl:
    1969           7 :                                 *res = (VALisnil(input1) || VALisnil(input2)) ? dbl_nil : single_case;
    1970           7 :                                 break;
    1971           0 :                         default:
    1972           0 :                                 msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1));
    1973             :                 }
    1974             :         }
    1975             : 
    1976         146 : bailout:
    1977         146 :         BBPreclaim(st);
    1978         146 :         unfix_inputs(6, b, c, p, o, s, e);
    1979         146 :         finalize_output(res, r, msg);
    1980         146 :         return msg;
    1981             : }
    1982             : 
    1983             : str
    1984          46 : SQLcovar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1985             : {
    1986          46 :         return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.covariance", GDKanalytical_covariance_samp, 1, 0.0f, dbl_nil);
    1987             : }
    1988             : 
    1989             : str
    1990          44 : SQLcovar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1991             : {
    1992          44 :         return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.covariancep", GDKanalytical_covariance_pop, 0, 0.0f, 0.0f);
    1993             : }
    1994             : 
    1995             : str
    1996          56 : SQLcorr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1997             : {
    1998          56 :         return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.corr", GDKanalytical_correlation, 0, dbl_nil, dbl_nil);
    1999             : }
    2000             : 
    2001             : str
    2002          54 : SQLstrgroup_concat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    2003             : {
    2004             :         BAT *r = NULL, *b = NULL, *sep = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
    2005             :         int separator_offset = 0, tpe, frame_type;
    2006             :         str msg = MAL_SUCCEED, separator = NULL;
    2007             :         bat *res = NULL;
    2008             : 
    2009             :         (void)cntxt;
    2010          54 :         if (pci->argc != 7 && pci->argc != 8)
    2011           0 :                 throw(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT "sql.strgroup_concat requires 7 or 8 arguments");
    2012             : 
    2013          54 :         tpe = getArgType(mb, pci, 2);
    2014          54 :         if (isaBatType(tpe))
    2015          30 :                 tpe = getBatType(tpe);
    2016          54 :         if (tpe == TYPE_str) /* there's a separator */
    2017             :                 separator_offset = 1;
    2018             :         else
    2019           7 :                 assert(tpe == TYPE_bit); /* otherwise it must be the partition's type */
    2020             : 
    2021          54 :         frame_type = *getArgReference_int(stk, pci, 4 + separator_offset);
    2022          54 :         assert(frame_type >= 0 && frame_type <= 6);
    2023             : 
    2024          54 :         if (isaBatType(getArgType(mb, pci, 1))) {
    2025          50 :                 res = getArgReference_bat(stk, pci, 0);
    2026             : 
    2027          50 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    2028           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY005) "Cannot access column descriptor");
    2029           0 :                         goto bailout;
    2030             :                 }
    2031          50 :                 if (!(r = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT))) {
    2032           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2033           0 :                         goto bailout;
    2034             :                 }
    2035          50 :                 if (separator_offset) {
    2036          45 :                         if (isaBatType(getArgType(mb, pci, 2))) {
    2037          30 :                                 if (!(sep = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
    2038           0 :                                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY005) "Cannot access column descriptor");
    2039           0 :                                         goto bailout;
    2040             :                                 }
    2041             :                         } else
    2042          15 :                                 separator = *getArgReference_str(stk, pci, 2);
    2043             :                 } else
    2044             :                         separator = ",";
    2045             : 
    2046          50 :                 if (isaBatType(getArgType(mb, pci, 2 + separator_offset)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 2 + separator_offset)))) {
    2047           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY005) "Cannot access column descriptor");
    2048           0 :                         goto bailout;
    2049             :                 }
    2050          50 :                 if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 3 + separator_offset)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3 + separator_offset)))) {
    2051           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY005) "Cannot access column descriptor");
    2052           0 :                         goto bailout;
    2053             :                 }
    2054          50 :                 if (frame_type < 3 && isaBatType(getArgType(mb, pci, 5 + separator_offset)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 5 + separator_offset)))) {
    2055           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY005) "Cannot access column descriptor");
    2056           0 :                         goto bailout;
    2057             :                 }
    2058          50 :                 if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6 + separator_offset)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 6 + separator_offset)))) {
    2059           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY005) "Cannot access column descriptor");
    2060           0 :                         goto bailout;
    2061             :                 }
    2062          50 :                 if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o)) || (sep && BATcount(b) != BATcount(sep))) {
    2063           0 :                         msg = createException(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT " Requires bats of identical size");
    2064           0 :                         goto bailout;
    2065             :                 }
    2066          50 :                 if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
    2067           0 :                         msg = createException(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
    2068           0 :                         goto bailout;
    2069             :                 }
    2070             : 
    2071          50 :                 assert((separator && !sep) || (!separator && sep)); /* only one of them must be set */
    2072          50 :                 if (GDKanalytical_str_group_concat(r, p, o, b, sep, s, e, separator, frame_type) != GDK_SUCCEED)
    2073           0 :                         msg = createException(SQL, "sql.strgroup_concat", GDK_EXCEPTION);
    2074             :         } else {
    2075           4 :                 str *res = getArgReference_str(stk, pci, 0);
    2076           4 :                 str in = *getArgReference_str(stk, pci, 1);
    2077             : 
    2078           4 :                 if (strNil(in)) {
    2079           3 :                         *res = GDKstrdup(str_nil);
    2080           1 :                 } else if (separator_offset) {
    2081           1 :                         str sep = *getArgReference_str(stk, pci, 2);
    2082           2 :                         size_t l1 = strlen(in), l2 = strNil(sep) ? 0 : strlen(sep);
    2083             : 
    2084           1 :                         if ((*res = GDKmalloc(l1+l2+1))) {
    2085           1 :                                 if (l1)
    2086           1 :                                         memcpy(*res, in, l1);
    2087           1 :                                 if (l2)
    2088           0 :                                         memcpy((*res)+l1, sep, l2);
    2089           1 :                                 (*res)[l1+l2] = '\0';
    2090             :                         }
    2091             :                 } else {
    2092           0 :                         *res = GDKstrdup(in);
    2093             :                 }
    2094           4 :                 if (!*res)
    2095           0 :                         msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2096             :         }
    2097             : 
    2098           4 : bailout:
    2099          54 :         unfix_inputs(6, b, sep, p, o, s, e);
    2100          54 :         finalize_output(res, r, msg);
    2101          54 :         return msg;
    2102             : }

Generated by: LCOV version 1.14