LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statistics.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 262 378 69.3 %
Date: 2024-10-07 21:21:43 Functions: 2 6 33.3 %

          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             : /* (c) M.L. Kersten
      14             : Most optimizers need easy access to key information
      15             : for proper plan generation. Amongst others, this
      16             : information consists of the tuple count, size,
      17             : min- and max-value, and the null-density.
      18             : 
      19             : We made need an directly accessible structure to speedup
      20             : analysis by optimizers.
      21             : */
      22             : #include "monetdb_config.h"
      23             : #include "sql_statistics.h"
      24             : 
      25             : static str
      26           0 : sql_set_stats(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int type)
      27             : {
      28           0 :         mvc *m = NULL;
      29           0 :         str sch = NULL, tbl = NULL, col = NULL, msg = MAL_SUCCEED;
      30             : 
      31           0 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
      32             :                 return msg;
      33           0 :         if ((msg = checkSQLContext(cntxt)) != NULL)
      34             :                 return msg;
      35             : 
      36           0 :         sch = *getArgReference_str(stk, pci, 1);
      37           0 :         tbl = *getArgReference_str(stk, pci, 2);
      38           0 :         col = *getArgReference_str(stk, pci, 3);
      39             : 
      40           0 :         sql_schema *s = mvc_bind_schema(m, sch);
      41           0 :         sql_table *t = s?mvc_bind_table(m, s, tbl):NULL;
      42           0 :         sql_column *c = t?mvc_bind_column(m, t, col):NULL;
      43           0 :         if (!c || !t || !s)
      44           0 :                 throw(SQL, "sql.set_stats", SQLSTATE(42000) "Cannot not find Column '%s.%s.%s'", sch, tbl, col);
      45           0 :         sql_trans *tr = m->session->tr;
      46           0 :     sqlstore *store = tr->store;
      47           0 :         if (type > 0) {
      48           0 :                 if (getArgType(mb, pci, 4) != c->type.type->localtype)
      49           0 :                         throw(SQL, "sql.set_stats", SQLSTATE(42000) "Wrong value type '%s'", BATatoms[getArgType(mb, pci, 4)].name);
      50           0 :                 ptr val = getArgReference(stk, pci, 4);
      51           0 :                 store->storage_api.set_stats_col(tr, c, NULL, type==1?val:NULL, type==2?val:NULL);
      52             :         } else { /* count lng type */
      53           0 :                 if (getArgType(mb, pci, 4) != TYPE_lng)
      54           0 :                         throw(SQL, "sql.set_stats", SQLSTATE(42000) "Wrong value type '%s'", BATatoms[getArgType(mb, pci, 4)].name);
      55           0 :                 lng cnt = *getArgReference_lng(stk, pci, 4);
      56           0 :                 double est = (double) cnt;
      57           0 :                 store->storage_api.set_stats_col(tr, c, &est, NULL, NULL);
      58             :         }
      59             :         return msg;
      60             : }
      61             : 
      62             : str
      63           0 : sql_set_count_distinct(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      64             : {
      65           0 :         return sql_set_stats(cntxt, mb, stk, pci, 0);
      66             : }
      67             : 
      68             : str
      69           0 : sql_set_min(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      70             : {
      71           0 :         return sql_set_stats(cntxt, mb, stk, pci, 1);
      72             : }
      73             : 
      74             : str
      75           0 : sql_set_max(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      76             : {
      77           0 :         return sql_set_stats(cntxt, mb, stk, pci, 2);
      78             : }
      79             : 
      80             : str
      81          49 : sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      82             : {
      83          49 :         mvc *m = NULL;
      84          49 :         sql_trans *tr = NULL;
      85          49 :         str sch = NULL, tbl = NULL, col = NULL, msg = MAL_SUCCEED;
      86          49 :         int argc = pci->argc, sfnd = 0, tfnd = 0, cfnd = 0;
      87             : 
      88          49 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
      89             :                 return msg;
      90          49 :         if ((msg = checkSQLContext(cntxt)) != NULL)
      91             :                 return msg;
      92             : 
      93          49 :         tr = m->session->tr;
      94          49 :         switch (argc) {
      95          12 :         case 4:
      96          12 :                 col = *getArgReference_str(stk, pci, 3);
      97          12 :                 if (strNil(col))
      98           0 :                         throw(SQL, "sql.analyze", SQLSTATE(42000) "Column name cannot be NULL");
      99             :                 /* fall through */
     100             :         case 3:
     101          44 :                 tbl = *getArgReference_str(stk, pci, 2);
     102          44 :                 if (strNil(tbl))
     103           0 :                         throw(SQL, "sql.analyze", SQLSTATE(42000) "Table name cannot be NULL");
     104             :                 /* fall through */
     105             :         case 2:
     106          49 :                 sch = *getArgReference_str(stk, pci, 1);
     107          49 :                 if (strNil(sch))
     108           0 :                         throw(SQL, "sql.analyze", SQLSTATE(42000) "Schema name cannot be NULL");
     109             :         }
     110             : 
     111          49 :         TRC_DEBUG(SQL_PARSER, "analyze %s.%s.%s\n", (sch ? sch : ""), (tbl ? tbl : " "), (col ? col : " "));
     112             : 
     113             :         /* Do all the validations before doing any analyze */
     114          49 :         struct os_iter si;
     115          49 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     116         400 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     117         352 :                 sql_schema *s = (sql_schema *)b;
     118         352 :                 if (s->base.name[0] == '%')
     119         304 :                         continue;
     120             : 
     121         303 :                 if (sch && strcmp(s->base.name, sch))
     122         255 :                         continue;
     123          48 :                 sfnd = 1;
     124          48 :                 struct os_iter oi;
     125          48 :                 os_iterator(&oi, s->tables, tr, NULL);
     126        5215 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     127        5168 :                         sql_table *t = (sql_table *)b;
     128             : 
     129        5168 :                         if (tbl && strcmp(t->base.name, tbl))
     130        4870 :                                 continue;
     131          44 :                         if (tbl && !isTable(t))
     132           1 :                                 throw(SQL, "sql.analyze", SQLSTATE(42S02) "%s '%s' is not persistent", TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
     133         297 :                         if (isTable(t) && ol_first_node(t->columns)) {
     134         124 :                                 bool allowed = table_privs(m, t, PRIV_SELECT);
     135         124 :                                 tfnd |= allowed;
     136         622 :                                 for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     137         498 :                                         sql_column *c = (sql_column *) ncol->data;
     138             : 
     139         498 :                                         if (col && strcmp(c->base.name, col))
     140          18 :                                                 continue;
     141         480 :                                         if (!allowed && !column_privs(m, c, PRIV_SELECT))
     142           0 :                                                 continue;
     143             :                                         cfnd = 1;
     144             :                                         tfnd |= cfnd;
     145             :                                 }
     146             :                         }
     147             :                 }
     148             :         }
     149          48 :         if (sch && !sfnd)
     150           1 :                 throw(SQL, "sql.analyze", SQLSTATE(3F000) "Schema '%s' does not exist", sch);
     151          47 :         if (tbl && !tfnd)
     152           0 :                 throw(SQL, "sql.analyze", SQLSTATE(42S02) "Table '%s' does not exist", tbl);
     153          47 :         if (col && !cfnd)
     154           0 :                 throw(SQL, "sql.analyze", SQLSTATE(38000) "Column '%s' does not exist", col);
     155             : 
     156          47 :         sqlstore *store = tr->store;
     157          47 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     158         384 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     159         337 :                 sql_schema *s = (sql_schema *)b;
     160         337 :                 if (b->name[0] == '%')
     161         290 :                         continue;
     162             : 
     163         290 :                 if (sch && strcmp(sch, b->name))
     164         243 :                         continue;
     165          47 :                 struct os_iter oi;
     166          47 :                 os_iterator(&oi, s->tables, tr, NULL);
     167        5214 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     168        5167 :                         sql_table *t = (sql_table *) b;
     169             : 
     170        5167 :                         if (tbl && strcmp(b->name, tbl))
     171        4870 :                                 continue;
     172         297 :                         if (isTable(t) && ol_first_node(t->columns)) {
     173         124 :                                 bool allowed = table_privs(m, t, PRIV_SELECT);
     174         622 :                                 for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     175         498 :                                         sql_column *c = (sql_column *) ncol->data;
     176         498 :                                         if (!allowed && !column_privs(m, c, PRIV_SELECT))
     177           0 :                                                 continue;
     178         498 :                                         BAT *b, *unq;
     179         498 :                                         ptr mn, mx;
     180             : 
     181         498 :                                         if (col && strcmp(c->base.name, col))
     182          18 :                                                 continue;
     183             : 
     184         480 :                                         int access = c->storage_type && c->storage_type[0] == 'D' ? RD_EXT : RDONLY;
     185         480 :                                         if (!(b = store->storage_api.bind_col(tr, c, access)))
     186           0 :                                                 continue; /* At the moment we ignore the error, but maybe we can change this */
     187         480 :                                         if (VIEWtparent(b)) { /* If it is a view get the parent BAT */
     188         479 :                                                 BAT *nb = BATdescriptor(VIEWtparent(b));
     189         479 :                                                 BBPunfix(b->batCacheid);
     190         479 :                                                 b = nb;
     191         479 :                                                 if (b == NULL)
     192           0 :                                                         continue;
     193             :                                         }
     194             : 
     195             :                                         /* Collect new sorted and revsorted properties */
     196         480 :                                         (void) BATordered(b);
     197         480 :                                         (void) BATordered_rev(b);
     198             : 
     199             :                                         /* Check for nils existence */
     200         480 :                                         (void) BATcount_no_nil(b, NULL);
     201             : 
     202             :                                         /* Test if column is unique */
     203         480 :                                         if ((unq = BATunique(b, NULL)))
     204         480 :                                                 BBPunfix(unq->batCacheid);
     205             : 
     206             :                                         /* Guess number of uniques if not entirely unique */
     207         480 :                                         (void) BATguess_uniques(b, NULL);
     208             : 
     209             :                                         /* Collect min and max values */
     210         480 :                                         mn = BATmin(b, NULL);
     211         480 :                                         GDKfree(mn);
     212         480 :                                         mx = BATmax(b, NULL);
     213         480 :                                         GDKfree(mx);
     214         480 :                                         BBPunfix(b->batCacheid);
     215             :                                 }
     216             :                         }
     217             :                 }
     218             :         }
     219             :         return MAL_SUCCEED;
     220             : }
     221             : 
     222             : str
     223         217 : sql_statistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     224             : {
     225         217 :         BAT *cid, *sch, *tab, *col, *type, *width, *count, *unique, *nils, *minval, *maxval, *sorted, *revsorted;
     226         217 :         mvc *m = NULL;
     227         217 :         sql_trans *tr = NULL;
     228         217 :         sqlstore *store = NULL;
     229         217 :         bat *rcid = getArgReference_bat(stk, pci, 0);
     230         217 :         bat *rsch = getArgReference_bat(stk, pci, 1);
     231         217 :         bat *rtab = getArgReference_bat(stk, pci, 2);
     232         217 :         bat *rcol = getArgReference_bat(stk, pci, 3);
     233         217 :         bat *rtype = getArgReference_bat(stk, pci, 4);
     234         217 :         bat *rwidth = getArgReference_bat(stk, pci, 5);
     235         217 :         bat *rcount = getArgReference_bat(stk, pci, 6);
     236         217 :         bat *runique = getArgReference_bat(stk, pci, 7);
     237         217 :         bat *rnils = getArgReference_bat(stk, pci, 8);
     238         217 :         bat *rminval = getArgReference_bat(stk, pci, 9);
     239         217 :         bat *rmaxval = getArgReference_bat(stk, pci, 10);
     240         217 :         bat *rsorted = getArgReference_bat(stk, pci, 11);
     241         217 :         bat *rrevsorted = getArgReference_bat(stk, pci, 12);
     242         217 :         str sname = NULL, tname = NULL, cname = NULL, msg = MAL_SUCCEED;
     243         217 :         struct os_iter si = {0};
     244         217 :         BUN nrows = 0;
     245         217 :         int sfnd = 0, tfnd = 0, cfnd = 0;
     246         217 :         size_t buflen = 0;
     247         217 :         char *buf = NULL, *nval = NULL;
     248             : 
     249         217 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
     250             :                 return msg;
     251         217 :         if ((msg = checkSQLContext(cntxt)) != NULL)
     252             :                 return msg;
     253             : 
     254         217 :         if (pci->argc - pci->retc >= 1) {
     255           6 :                 sname = *getArgReference_str(stk, pci, pci->retc);
     256           6 :                 if (strNil(sname))
     257           0 :                         throw(SQL, "sql.statistics", SQLSTATE(42000) "Schema name cannot be NULL");
     258             :         }
     259         217 :         if (pci->argc - pci->retc >= 2) {
     260           6 :                 tname = *getArgReference_str(stk, pci, pci->retc + 1);
     261           6 :                 if (strNil(tname))
     262           0 :                         throw(SQL, "sql.statistics", SQLSTATE(42000) "Table name cannot be NULL");
     263             :         }
     264         217 :         if (pci->argc - pci->retc >= 3) {
     265           0 :                 cname = *getArgReference_str(stk, pci, pci->retc + 2);
     266           0 :                 if (strNil(cname))
     267           0 :                         throw(SQL, "sql.statistics", SQLSTATE(42000) "Column name cannot be NULL");
     268             :         }
     269             : 
     270         217 :         tr = m->session->tr;
     271         217 :         store = tr->store;
     272             :         /* Do all the validations before retrieving any statistics */
     273         217 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     274        1742 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     275        1525 :                 sql_schema *s = (sql_schema *)b;
     276        1525 :                 if (s->base.name[0] == '%')
     277         247 :                         continue;
     278             : 
     279        1308 :                 if (sname && strcmp(s->base.name, sname))
     280          30 :                         continue;
     281        1278 :                 sfnd = 1;
     282        1278 :                 struct os_iter oi;
     283        1278 :                 os_iterator(&oi, s->tables, tr, NULL);
     284       32230 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     285       30952 :                         sql_table *t = (sql_table *)b;
     286             : 
     287       30952 :                         if (tname && strcmp(t->base.name, tname))
     288         750 :                                 continue;
     289           6 :                         if (tname && !isTable(t))
     290           0 :                                 throw(SQL, "sql.statistics", SQLSTATE(42S02) "%s '%s' is not persistent", TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
     291       30202 :                         if (isTable(t) && ol_first_node(t->columns)) {
     292        9520 :                                 bool allowed = table_privs(m, t, PRIV_SELECT);
     293        9520 :                                 tfnd |= allowed;
     294       58132 :                                 for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     295       48612 :                                         sql_column *c = (sql_column *) ncol->data;
     296             : 
     297       48612 :                                         if (cname && strcmp(c->base.name, cname))
     298           0 :                                                 continue;
     299       48612 :                                         nrows++;
     300       48612 :                                         if (!allowed && !column_privs(m, c, PRIV_SELECT))
     301         130 :                                                 continue;
     302             :                                         cfnd = 1;
     303             :                                         tfnd |= cfnd;
     304             :                                 }
     305             :                         }
     306             :                 }
     307             :         }
     308         217 :         if (sname && !sfnd)
     309           0 :                 throw(SQL, "sql.statistics", SQLSTATE(3F000) "Schema '%s' does not exist", sname);
     310         217 :         if (tname && !tfnd)
     311           0 :                 throw(SQL, "sql.statistics", SQLSTATE(42S02) "Table '%s' does not exist", tname);
     312         217 :         if (cname && !cfnd)
     313           0 :                 throw(SQL, "sql.statistics", SQLSTATE(38000) "Column '%s' does not exist", cname);
     314             : 
     315         217 :         cid = COLnew(0, TYPE_int, nrows, TRANSIENT);
     316         217 :         sch = COLnew(0, TYPE_str, nrows, TRANSIENT);
     317         217 :         tab = COLnew(0, TYPE_str, nrows, TRANSIENT);
     318         217 :         col = COLnew(0, TYPE_str, nrows, TRANSIENT);
     319         217 :         type = COLnew(0, TYPE_str, nrows, TRANSIENT);
     320         217 :         width = COLnew(0, TYPE_int, nrows, TRANSIENT);
     321         217 :         count = COLnew(0, TYPE_lng, nrows, TRANSIENT);
     322         217 :         unique = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     323         217 :         nils = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     324         217 :         minval = COLnew(0, TYPE_str, nrows, TRANSIENT);
     325         217 :         maxval = COLnew(0, TYPE_str, nrows, TRANSIENT);
     326         217 :         sorted = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     327         217 :         revsorted = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     328             : 
     329         217 :         if (!cid || !sch || !tab || !col || !type || !width || !count || !unique || !nils || !minval || !maxval || !sorted || !revsorted) {
     330           0 :                 msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     331           0 :                 goto bailout;
     332             :         }
     333             : 
     334         217 :         si = (struct os_iter) {0};
     335         217 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     336        1742 :         for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     337        1525 :                 sql_schema *s = (sql_schema *) b;
     338        1525 :                 if ((sname && strcmp(b->name, sname)) || b->name[0] == '%')
     339         247 :                         continue;
     340        1278 :                 if (s->tables) {
     341        1278 :                         struct os_iter oi;
     342             : 
     343        1278 :                         os_iterator(&oi, s->tables, tr, NULL);
     344       32230 :                         for (sql_base *bt = oi_next(&oi); bt; bt = oi_next(&oi)) {
     345       30952 :                                 sql_table *t = (sql_table *) bt;
     346       30952 :                                 if (tname && strcmp(bt->name, tname))
     347         750 :                                         continue;
     348       30202 :                                 if (isTable(t) && ol_first_node(t->columns)) {
     349        9520 :                                         bool allowed = table_privs(m, t, PRIV_SELECT);
     350       58132 :                                         for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     351       48612 :                                                 sql_column *c = (sql_column *) ncol->data;
     352       48612 :                                                 if (!allowed && !column_privs(m, c, PRIV_SELECT))
     353         130 :                                                         continue;
     354       48482 :                                                 int w;
     355       48482 :                                                 lng cnt;
     356       48482 :                                                 bit un, hnils, issorted, isrevsorted, dict;
     357       48482 :                                                 BAT *qd = NULL, *fb = NULL, *re = NULL;
     358             : 
     359       48482 :                                                 if (cname && strcmp(c->base.name, cname))
     360           0 :                                                         continue;
     361             : 
     362       48482 :                                                 if (!(qd = store->storage_api.bind_col(tr, c, QUICK))) {
     363           0 :                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     364           0 :                                                         goto bailout;
     365             :                                                 }
     366       48482 :                                                 BATiter qdi = bat_iterator(qd);
     367       48482 :                                                 BATiter posi;
     368       48482 :                                                 if ((dict = (c->storage_type && c->storage_type[0] == 'D'))) {
     369           0 :                                                         if (!(re = store->storage_api.bind_col(tr, c, RD_EXT))) {
     370           0 :                                                                 bat_iterator_end(&qdi);
     371           0 :                                                                 msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     372           0 :                                                                 goto bailout;
     373             :                                                         }
     374           0 :                                                         BATiter rei = bat_iterator(re);
     375           0 :                                                         if (VIEWtparent(re)) { /* If it is a view get the parent BAT */
     376           0 :                                                                 BAT *nb = BATdescriptor(VIEWtparent(re));
     377           0 :                                                                 BBPunfix(re->batCacheid);
     378           0 :                                                                 re = nb;
     379           0 :                                                                 if (re == NULL) {
     380           0 :                                                                         bat_iterator_end(&qdi);
     381           0 :                                                                         bat_iterator_end(&rei);
     382           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     383           0 :                                                                         goto bailout;
     384             :                                                                 }
     385             :                                                         }
     386           0 :                                                         issorted = qdi.sorted && rei.sorted;
     387           0 :                                                         isrevsorted = qdi.revsorted && rei.revsorted;
     388           0 :                                                         hnils = !rei.nonil || rei.nil;
     389           0 :                                                         posi = bat_iterator_copy(&rei);
     390           0 :                                                         bat_iterator_end(&rei);
     391             :                                                 } else {
     392       48482 :                                                         issorted = qdi.sorted;
     393       48482 :                                                         isrevsorted = qdi.revsorted;
     394       48482 :                                                         hnils = !qdi.nonil || qdi.nil;
     395       48482 :                                                         posi = bat_iterator_copy(&qdi);
     396             :                                                 }
     397             : 
     398       48482 :                                                 w = qdi.width;
     399       48482 :                                                 cnt = qdi.count;
     400       48482 :                                                 un = qdi.key;
     401       48482 :                                                 bat_iterator_end(&qdi);
     402             : 
     403       96964 :                                                 if (BUNappend(cid, &c->base.id, false) != GDK_SUCCEED ||
     404       96964 :                                                         BUNappend(sch, b->name, false) != GDK_SUCCEED ||
     405       96964 :                                                         BUNappend(tab, bt->name, false) != GDK_SUCCEED ||
     406       96964 :                                                         BUNappend(col, c->base.name, false) != GDK_SUCCEED ||
     407       96964 :                                                         BUNappend(type, c->type.type->base.name, false) != GDK_SUCCEED ||
     408       96964 :                                                         BUNappend(width, &w, false) != GDK_SUCCEED ||
     409       96964 :                                                         BUNappend(count, &cnt, false) != GDK_SUCCEED ||
     410       96964 :                                                         BUNappend(unique, &un, false) != GDK_SUCCEED ||
     411       96964 :                                                         BUNappend(nils, &hnils, false) != GDK_SUCCEED ||
     412       96964 :                                                         BUNappend(sorted, &issorted, false) != GDK_SUCCEED ||
     413       48482 :                                                         BUNappend(revsorted, &isrevsorted, false) != GDK_SUCCEED) {
     414           0 :                                                         bat_iterator_end(&posi);
     415           0 :                                                         BBPreclaim(re);
     416           0 :                                                         goto bailout;
     417             :                                                 }
     418             : 
     419       65372 :                                                 if (posi.minpos != BUN_NONE || posi.maxpos != BUN_NONE) {
     420       16890 :                                                         bat_iterator_end(&posi);
     421       16890 :                                                         if (dict) {
     422             :                                                                 fb = re;
     423             :                                                         } else {
     424       16890 :                                                                 if (!(fb = store->storage_api.bind_col(tr, c, RDONLY))) {
     425           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     426           0 :                                                                         goto bailout;
     427             :                                                                 }
     428       16890 :                                                                 if (VIEWtparent(fb)) { /* If it is a view get the parent BAT */
     429       16890 :                                                                         BAT *nb = BATdescriptor(VIEWtparent(fb));
     430       16890 :                                                                         BBPunfix(fb->batCacheid);
     431       16890 :                                                                         fb = nb;
     432       16890 :                                                                         if (fb == NULL) {
     433           0 :                                                                                 msg = createException(SQL, "sql.statistics", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     434           0 :                                                                                 goto bailout;
     435             :                                                                         }
     436             :                                                                 }
     437             :                                                         }
     438             : 
     439       16890 :                                                         BATiter fbi = bat_iterator(fb);
     440       16890 :                                                         ssize_t (*tostr)(str*,size_t*,const void*,bool) = BATatoms[fbi.type].atomToStr;
     441       16890 :                                                         if (fbi.minpos != BUN_NONE) {
     442       16441 :                                                                 if (tostr(&buf, &buflen, BUNtail(fbi, fbi.minpos), false) < 0) {
     443           0 :                                                                         bat_iterator_end(&fbi);
     444           0 :                                                                         BBPunfix(fb->batCacheid);
     445           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     446           0 :                                                                         goto bailout;
     447             :                                                                 }
     448       16441 :                                                                 nval = buf;
     449             :                                                         } else {
     450             :                                                                 nval = (char *) str_nil;
     451             :                                                         }
     452       16890 :                                                         if (BUNappend(minval, nval, false) != GDK_SUCCEED) {
     453           0 :                                                                 bat_iterator_end(&fbi);
     454           0 :                                                                 BBPunfix(fb->batCacheid);
     455           0 :                                                                 goto bailout;
     456             :                                                         }
     457             : 
     458       16890 :                                                         if (fbi.maxpos != BUN_NONE) {
     459       16734 :                                                                 if (tostr(&buf, &buflen, BUNtail(fbi, fbi.maxpos), false) < 0) {
     460           0 :                                                                         bat_iterator_end(&fbi);
     461           0 :                                                                         BBPunfix(fb->batCacheid);
     462           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     463           0 :                                                                         goto bailout;
     464             :                                                                 }
     465       16734 :                                                                 nval = buf;
     466             :                                                         } else {
     467             :                                                                 nval = (char *) str_nil;
     468             :                                                         }
     469       16890 :                                                         bat_iterator_end(&fbi);
     470       16890 :                                                         if (BUNappend(maxval, nval, false) != GDK_SUCCEED) {
     471           0 :                                                                 BBPunfix(fb->batCacheid);
     472           0 :                                                                 goto bailout;
     473             :                                                         }
     474       16890 :                                                         BBPunfix(fb->batCacheid);
     475       31592 :                                                 } else if (BUNappend(minval, str_nil, false) != GDK_SUCCEED || BUNappend(maxval, str_nil, false) != GDK_SUCCEED) {
     476           0 :                                                         bat_iterator_end(&posi);
     477           0 :                                                         BBPreclaim(re);
     478           0 :                                                         goto bailout;
     479       31592 :                                                 } else if (re) {
     480           0 :                                                         bat_iterator_end(&posi);
     481           0 :                                                         BBPunfix(re->batCacheid);
     482             :                                                 } else {
     483       31592 :                                                         bat_iterator_end(&posi);
     484             :                                                 }
     485             :                                         }
     486             :                                 }
     487             :                         }
     488             :                 }
     489             :         }
     490             : 
     491         217 :         GDKfree(buf);
     492         217 :         *rcid = cid->batCacheid;
     493         217 :         BBPkeepref(cid);
     494         217 :         *rsch = sch->batCacheid;
     495         217 :         BBPkeepref(sch);
     496         217 :         *rtab = tab->batCacheid;
     497         217 :         BBPkeepref(tab);
     498         217 :         *rcol = col->batCacheid;
     499         217 :         BBPkeepref(col);
     500         217 :         *rtype = type->batCacheid;
     501         217 :         BBPkeepref(type);
     502         217 :         *rwidth = width->batCacheid;
     503         217 :         BBPkeepref(width);
     504         217 :         *rcount = count->batCacheid;
     505         217 :         BBPkeepref(count);
     506         217 :         *runique = unique->batCacheid;
     507         217 :         BBPkeepref(unique);
     508         217 :         *rnils = nils->batCacheid;
     509         217 :         BBPkeepref(nils);
     510         217 :         *rminval = minval->batCacheid;
     511         217 :         BBPkeepref(minval);
     512         217 :         *rmaxval = maxval->batCacheid;
     513         217 :         BBPkeepref(maxval);
     514         217 :         *rsorted = sorted->batCacheid;
     515         217 :         BBPkeepref(sorted);
     516         217 :         *rrevsorted = revsorted->batCacheid;
     517         217 :         BBPkeepref(revsorted);
     518         217 :         return MAL_SUCCEED;
     519           0 : bailout:
     520           0 :         GDKfree(buf);
     521           0 :         BBPreclaim(cid);
     522           0 :         BBPreclaim(sch);
     523           0 :         BBPreclaim(tab);
     524           0 :         BBPreclaim(col);
     525           0 :         BBPreclaim(type);
     526           0 :         BBPreclaim(width);
     527           0 :         BBPreclaim(count);
     528           0 :         BBPreclaim(unique);
     529           0 :         BBPreclaim(nils);
     530           0 :         BBPreclaim(minval);
     531           0 :         BBPreclaim(maxval);
     532           0 :         BBPreclaim(sorted);
     533           0 :         BBPreclaim(revsorted);
     534           0 :         if (!msg)
     535           0 :                 msg = createException(SQL, "sql.statistics", GDK_EXCEPTION);
     536             :         return msg;
     537             : }

Generated by: LCOV version 1.14