LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_rank.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 938 1334 70.3 %
Date: 2024-12-19 23:10:26 Functions: 38 38 100.0 %

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

Generated by: LCOV version 1.14