LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statistics.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 261 380 68.7 %
Date: 2024-04-26 00:35:57 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          34 : sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      82             : {
      83          34 :         mvc *m = NULL;
      84          34 :         sql_trans *tr = NULL;
      85          34 :         str sch = NULL, tbl = NULL, col = NULL, msg = MAL_SUCCEED;
      86          34 :         int argc = pci->argc, sfnd = 0, tfnd = 0, cfnd = 0;
      87             : 
      88          34 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
      89             :                 return msg;
      90          34 :         if ((msg = checkSQLContext(cntxt)) != NULL)
      91             :                 return msg;
      92             : 
      93          34 :         tr = m->session->tr;
      94          34 :         switch (argc) {
      95           2 :         case 4:
      96           2 :                 col = *getArgReference_str(stk, pci, 3);
      97           2 :                 if (strNil(col))
      98           0 :                         throw(SQL, "sql.analyze", SQLSTATE(42000) "Column name cannot be NULL");
      99             :                 /* fall through */
     100             :         case 3:
     101          29 :                 tbl = *getArgReference_str(stk, pci, 2);
     102          29 :                 if (strNil(tbl))
     103           0 :                         throw(SQL, "sql.analyze", SQLSTATE(42000) "Table name cannot be NULL");
     104             :                 /* fall through */
     105             :         case 2:
     106          34 :                 sch = *getArgReference_str(stk, pci, 1);
     107          34 :                 if (strNil(sch))
     108           0 :                         throw(SQL, "sql.analyze", SQLSTATE(42000) "Schema name cannot be NULL");
     109             :         }
     110             : 
     111          34 :         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          34 :         struct os_iter si;
     115          34 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     116         275 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     117         242 :                 sql_schema *s = (sql_schema *)b;
     118         242 :                 if (s->base.name[0] == '%')
     119         209 :                         continue;
     120             : 
     121         208 :                 if (sch && strcmp(s->base.name, sch))
     122         175 :                         continue;
     123          33 :                 sfnd = 1;
     124          33 :                 struct os_iter oi;
     125          33 :                 os_iterator(&oi, s->tables, tr, NULL);
     126        3885 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     127        3853 :                         sql_table *t = (sql_table *)b;
     128             : 
     129        3853 :                         if (tbl && strcmp(t->base.name, tbl))
     130        3572 :                                 continue;
     131         309 :                         tfnd = 1;
     132          29 :                         if (tbl && !isTable(t))
     133           1 :                                 throw(SQL, "sql.analyze", SQLSTATE(42S02) "%s '%s' is not persistent", TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
     134         280 :                         if (!table_privs(m, t, PRIV_SELECT))
     135           0 :                                 throw(SQL, "sql.analyze", SQLSTATE(42000) "ANALYZE: access denied for %s to table '%s.%s'",
     136           0 :                                           get_string_global_var(m, "current_user"), t->s->base.name, t->base.name);
     137         280 :                         if (isTable(t) && ol_first_node(t->columns)) {
     138         568 :                                 for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     139         461 :                                         sql_column *c = (sql_column *) ncol->data;
     140             : 
     141         461 :                                         if (col && strcmp(c->base.name, col))
     142           2 :                                                 continue;
     143         459 :                                         cfnd = 1;
     144         459 :                                         if (!column_privs(m, c, PRIV_SELECT))
     145           0 :                                                 throw(SQL, "sql.analyze", SQLSTATE(42000) "ANALYZE: access denied for %s to column '%s' on table '%s.%s'",
     146           0 :                                                           get_string_global_var(m, "current_user"), c->base.name, t->s->base.name, t->base.name);
     147             :                                 }
     148             :                         }
     149             :                 }
     150             :         }
     151          33 :         if (sch && !sfnd)
     152           1 :                 throw(SQL, "sql.analyze", SQLSTATE(3F000) "Schema '%s' does not exist", sch);
     153          32 :         if (tbl && !tfnd)
     154           0 :                 throw(SQL, "sql.analyze", SQLSTATE(42S02) "Table '%s' does not exist", tbl);
     155          32 :         if (col && !cfnd)
     156           0 :                 throw(SQL, "sql.analyze", SQLSTATE(38000) "Column '%s' does not exist", col);
     157             : 
     158          32 :         sqlstore *store = tr->store;
     159          32 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     160         259 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     161         227 :                 sql_schema *s = (sql_schema *)b;
     162         227 :                 if (b->name[0] == '%')
     163         195 :                         continue;
     164             : 
     165         195 :                 if (sch && strcmp(sch, b->name))
     166         163 :                         continue;
     167          32 :                 struct os_iter oi;
     168          32 :                 os_iterator(&oi, s->tables, tr, NULL);
     169        3884 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     170        3852 :                         sql_table *t = (sql_table *) b;
     171             : 
     172        3852 :                         if (tbl && strcmp(b->name, tbl))
     173        3572 :                                 continue;
     174         280 :                         if (isTable(t) && ol_first_node(t->columns)) {
     175         568 :                                 for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     176         461 :                                         sql_column *c = (sql_column *) ncol->data;
     177         461 :                                         BAT *b, *unq;
     178         461 :                                         ptr mn, mx;
     179             : 
     180         461 :                                         if (col && strcmp(c->base.name, col))
     181           2 :                                                 continue;
     182             : 
     183         459 :                                         int access = c->storage_type && c->storage_type[0] == 'D' ? RD_EXT : RDONLY;
     184         459 :                                         if (!(b = store->storage_api.bind_col(tr, c, access)))
     185           0 :                                                 continue; /* At the moment we ignore the error, but maybe we can change this */
     186         459 :                                         if (isVIEW(b)) { /* If it is a view get the parent BAT */
     187         458 :                                                 BAT *nb = BATdescriptor(VIEWtparent(b));
     188         458 :                                                 BBPunfix(b->batCacheid);
     189         458 :                                                 b = nb;
     190         458 :                                                 if (b == NULL)
     191           0 :                                                         continue;
     192             :                                         }
     193             : 
     194             :                                         /* Collect new sorted and revsorted properties */
     195         459 :                                         (void) BATordered(b);
     196         459 :                                         (void) BATordered_rev(b);
     197             : 
     198             :                                         /* Check for nils existence */
     199         459 :                                         (void) BATcount_no_nil(b, NULL);
     200             : 
     201             :                                         /* Test if column is unique */
     202         459 :                                         if ((unq = BATunique(b, NULL)))
     203         459 :                                                 BBPunfix(unq->batCacheid);
     204             : 
     205             :                                         /* Guess number of uniques if not entirely unique */
     206         459 :                                         (void) BATguess_uniques(b, NULL);
     207             : 
     208             :                                         /* Collect min and max values */
     209         459 :                                         mn = BATmin(b, NULL);
     210         459 :                                         GDKfree(mn);
     211         459 :                                         mx = BATmax(b, NULL);
     212         459 :                                         GDKfree(mx);
     213         459 :                                         BBPunfix(b->batCacheid);
     214             :                                 }
     215             :                         }
     216             :                 }
     217             :         }
     218             :         return MAL_SUCCEED;
     219             : }
     220             : 
     221             : str
     222         154 : sql_statistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     223             : {
     224         154 :         BAT *cid, *sch, *tab, *col, *type, *width, *count, *unique, *nils, *minval, *maxval, *sorted, *revsorted;
     225         154 :         mvc *m = NULL;
     226         154 :         sql_trans *tr = NULL;
     227         154 :         sqlstore *store = NULL;
     228         154 :         bat *rcid = getArgReference_bat(stk, pci, 0);
     229         154 :         bat *rsch = getArgReference_bat(stk, pci, 1);
     230         154 :         bat *rtab = getArgReference_bat(stk, pci, 2);
     231         154 :         bat *rcol = getArgReference_bat(stk, pci, 3);
     232         154 :         bat *rtype = getArgReference_bat(stk, pci, 4);
     233         154 :         bat *rwidth = getArgReference_bat(stk, pci, 5);
     234         154 :         bat *rcount = getArgReference_bat(stk, pci, 6);
     235         154 :         bat *runique = getArgReference_bat(stk, pci, 7);
     236         154 :         bat *rnils = getArgReference_bat(stk, pci, 8);
     237         154 :         bat *rminval = getArgReference_bat(stk, pci, 9);
     238         154 :         bat *rmaxval = getArgReference_bat(stk, pci, 10);
     239         154 :         bat *rsorted = getArgReference_bat(stk, pci, 11);
     240         154 :         bat *rrevsorted = getArgReference_bat(stk, pci, 12);
     241         154 :         str sname = NULL, tname = NULL, cname = NULL, msg = MAL_SUCCEED;
     242         154 :         struct os_iter si = {0};
     243         154 :         BUN nrows = 0;
     244         154 :         int sfnd = 0, tfnd = 0, cfnd = 0;
     245         154 :         size_t buflen = 0;
     246         154 :         char *buf = NULL, *nval = NULL;
     247             : 
     248         154 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
     249             :                 return msg;
     250         154 :         if ((msg = checkSQLContext(cntxt)) != NULL)
     251             :                 return msg;
     252             : 
     253         154 :         if (pci->argc - pci->retc >= 1) {
     254           6 :                 sname = *getArgReference_str(stk, pci, pci->retc);
     255           6 :                 if (strNil(sname))
     256           0 :                         throw(SQL, "sql.statistics", SQLSTATE(42000) "Schema name cannot be NULL");
     257             :         }
     258         154 :         if (pci->argc - pci->retc >= 2) {
     259           6 :                 tname = *getArgReference_str(stk, pci, pci->retc + 1);
     260           6 :                 if (strNil(tname))
     261           0 :                         throw(SQL, "sql.statistics", SQLSTATE(42000) "Table name cannot be NULL");
     262             :         }
     263         154 :         if (pci->argc - pci->retc >= 3) {
     264           0 :                 cname = *getArgReference_str(stk, pci, pci->retc + 2);
     265           0 :                 if (strNil(cname))
     266           0 :                         throw(SQL, "sql.statistics", SQLSTATE(42000) "Column name cannot be NULL");
     267             :         }
     268             : 
     269         154 :         tr = m->session->tr;
     270         154 :         store = tr->store;
     271             :         /* Do all the validations before retrieving any statistics */
     272         154 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     273        1221 :         for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     274        1069 :                 sql_schema *s = (sql_schema *)b;
     275        1069 :                 if (s->base.name[0] == '%')
     276         182 :                         continue;
     277             : 
     278         917 :                 if (sname && strcmp(s->base.name, sname))
     279          30 :                         continue;
     280         887 :                 sfnd = 1;
     281         887 :                 struct os_iter oi;
     282         887 :                 os_iterator(&oi, s->tables, tr, NULL);
     283       22379 :                 for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
     284       21494 :                         sql_table *t = (sql_table *)b;
     285             : 
     286       21494 :                         if (tname && strcmp(t->base.name, tname))
     287         744 :                                 continue;
     288       20756 :                         tfnd = 1;
     289           6 :                         if (tname && !isTable(t))
     290           2 :                                 throw(SQL, "sql.statistics", SQLSTATE(42S02) "%s '%s' is not persistent", TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
     291       20750 :                         if (!table_privs(m, t, PRIV_SELECT))
     292           0 :                                 throw(SQL, "sql.statistics", SQLSTATE(42000) "STATISTICS: access denied for %s to table '%s.%s'",
     293           0 :                                           get_string_global_var(m, "current_user"), t->s->base.name, t->base.name);
     294       20750 :                         if (isTable(t) && ol_first_node(t->columns)) {
     295       39491 :                                 for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     296       33053 :                                         sql_column *c = (sql_column *) ncol->data;
     297             : 
     298       33053 :                                         if (cname && strcmp(c->base.name, cname))
     299           0 :                                                 continue;
     300       33053 :                                         cfnd = 1;
     301       33053 :                                         nrows++;
     302       33053 :                                         if (!column_privs(m, c, PRIV_SELECT))
     303           2 :                                                 throw(SQL, "sql.statistics", SQLSTATE(42000) "STATISTICS: access denied for %s to column '%s' on table '%s.%s'",
     304           2 :                                                           get_string_global_var(m, "current_user"), c->base.name, t->s->base.name, t->base.name);
     305             :                                 }
     306             :                         }
     307             :                 }
     308             :         }
     309         152 :         if (sname && !sfnd)
     310           0 :                 throw(SQL, "sql.statistics", SQLSTATE(3F000) "Schema '%s' does not exist", sname);
     311         152 :         if (tname && !tfnd)
     312           0 :                 throw(SQL, "sql.statistics", SQLSTATE(42S02) "Table '%s' does not exist", tname);
     313         152 :         if (cname && !cfnd)
     314           0 :                 throw(SQL, "sql.statistics", SQLSTATE(38000) "Column '%s' does not exist", cname);
     315             : 
     316         152 :         cid = COLnew(0, TYPE_int, nrows, TRANSIENT);
     317         152 :         sch = COLnew(0, TYPE_str, nrows, TRANSIENT);
     318         152 :         tab = COLnew(0, TYPE_str, nrows, TRANSIENT);
     319         152 :         col = COLnew(0, TYPE_str, nrows, TRANSIENT);
     320         152 :         type = COLnew(0, TYPE_str, nrows, TRANSIENT);
     321         152 :         width = COLnew(0, TYPE_int, nrows, TRANSIENT);
     322         152 :         count = COLnew(0, TYPE_lng, nrows, TRANSIENT);
     323         152 :         unique = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     324         152 :         nils = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     325         152 :         minval = COLnew(0, TYPE_str, nrows, TRANSIENT);
     326         152 :         maxval = COLnew(0, TYPE_str, nrows, TRANSIENT);
     327         152 :         sorted = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     328         152 :         revsorted = COLnew(0, TYPE_bit, nrows, TRANSIENT);
     329             : 
     330         152 :         if (!cid || !sch || !tab || !col || !type || !width || !count || !unique || !nils || !minval || !maxval || !sorted || !revsorted) {
     331           0 :                 msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     332           0 :                 goto bailout;
     333             :         }
     334             : 
     335         152 :         si = (struct os_iter) {0};
     336         152 :         os_iterator(&si, tr->cat->schemas, tr, NULL);
     337        1219 :         for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
     338        1067 :                 sql_schema *s = (sql_schema *) b;
     339        1067 :                 if ((sname && strcmp(b->name, sname)) || b->name[0] == '%')
     340         182 :                         continue;
     341         885 :                 if (s->tables) {
     342         885 :                         struct os_iter oi;
     343             : 
     344         885 :                         os_iterator(&oi, s->tables, tr, NULL);
     345       22377 :                         for (sql_base *bt = oi_next(&oi); bt; bt = oi_next(&oi)) {
     346       21492 :                                 sql_table *t = (sql_table *) bt;
     347       21492 :                                 if (tname && strcmp(bt->name, tname))
     348         744 :                                         continue;
     349       20748 :                                 if (isTable(t) && ol_first_node(t->columns)) {
     350       39489 :                                         for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
     351       33051 :                                                 sql_column *c = (sql_column *) ncol->data;
     352       33051 :                                                 int w;
     353       33051 :                                                 lng cnt;
     354       33051 :                                                 bit un, hnils, issorted, isrevsorted, dict;
     355       33051 :                                                 BAT *qd = NULL, *fb = NULL, *re = NULL;
     356             : 
     357       33051 :                                                 if (cname && strcmp(c->base.name, cname))
     358           0 :                                                         continue;
     359             : 
     360       33051 :                                                 if (!(qd = store->storage_api.bind_col(tr, c, QUICK))) {
     361           0 :                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     362           0 :                                                         goto bailout;
     363             :                                                 }
     364       33051 :                                                 BATiter qdi = bat_iterator(qd);
     365       33051 :                                                 BATiter posi;
     366       33051 :                                                 if ((dict = (c->storage_type && c->storage_type[0] == 'D'))) {
     367           0 :                                                         if (!(re = store->storage_api.bind_col(tr, c, RD_EXT))) {
     368           0 :                                                                 bat_iterator_end(&qdi);
     369           0 :                                                                 msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     370           0 :                                                                 goto bailout;
     371             :                                                         }
     372           0 :                                                         BATiter rei = bat_iterator(re);
     373           0 :                                                         if (isVIEW(re)) { /* If it is a view get the parent BAT */
     374           0 :                                                                 BAT *nb = BATdescriptor(VIEWtparent(re));
     375           0 :                                                                 BBPunfix(re->batCacheid);
     376           0 :                                                                 re = nb;
     377           0 :                                                                 if (re == NULL) {
     378           0 :                                                                         bat_iterator_end(&qdi);
     379           0 :                                                                         bat_iterator_end(&rei);
     380           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     381           0 :                                                                         goto bailout;
     382             :                                                                 }
     383             :                                                         }
     384           0 :                                                         issorted = qdi.sorted && rei.sorted;
     385           0 :                                                         isrevsorted = qdi.revsorted && rei.revsorted;
     386           0 :                                                         hnils = !rei.nonil || rei.nil;
     387           0 :                                                         posi = bat_iterator_copy(&rei);
     388           0 :                                                         bat_iterator_end(&rei);
     389             :                                                 } else {
     390       33051 :                                                         issorted = qdi.sorted;
     391       33051 :                                                         isrevsorted = qdi.revsorted;
     392       33051 :                                                         hnils = !qdi.nonil || qdi.nil;
     393       33051 :                                                         posi = bat_iterator_copy(&qdi);
     394             :                                                 }
     395             : 
     396       33051 :                                                 w = qdi.width;
     397       33051 :                                                 cnt = qdi.count;
     398       33051 :                                                 un = qdi.key;
     399       33051 :                                                 bat_iterator_end(&qdi);
     400             : 
     401       66102 :                                                 if (BUNappend(cid, &c->base.id, false) != GDK_SUCCEED ||
     402       66102 :                                                         BUNappend(sch, b->name, false) != GDK_SUCCEED ||
     403       66102 :                                                         BUNappend(tab, bt->name, false) != GDK_SUCCEED ||
     404       66102 :                                                         BUNappend(col, c->base.name, false) != GDK_SUCCEED ||
     405       66102 :                                                         BUNappend(type, c->type.type->base.name, false) != GDK_SUCCEED ||
     406       66102 :                                                         BUNappend(width, &w, false) != GDK_SUCCEED ||
     407       66102 :                                                         BUNappend(count, &cnt, false) != GDK_SUCCEED ||
     408       66102 :                                                         BUNappend(unique, &un, false) != GDK_SUCCEED ||
     409       66102 :                                                         BUNappend(nils, &hnils, false) != GDK_SUCCEED ||
     410       66102 :                                                         BUNappend(sorted, &issorted, false) != GDK_SUCCEED ||
     411       33051 :                                                         BUNappend(revsorted, &isrevsorted, false) != GDK_SUCCEED) {
     412           0 :                                                         bat_iterator_end(&posi);
     413           0 :                                                         BBPreclaim(re);
     414           0 :                                                         goto bailout;
     415             :                                                 }
     416             : 
     417       48608 :                                                 if (posi.minpos != BUN_NONE || posi.maxpos != BUN_NONE) {
     418       15557 :                                                         bat_iterator_end(&posi);
     419       15557 :                                                         if (dict) {
     420             :                                                                 fb = re;
     421             :                                                         } else {
     422       15557 :                                                                 if (!(fb = store->storage_api.bind_col(tr, c, RDONLY))) {
     423           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     424           0 :                                                                         goto bailout;
     425             :                                                                 }
     426       15557 :                                                                 if (isVIEW(fb)) { /* If it is a view get the parent BAT */
     427       15557 :                                                                         BAT *nb = BATdescriptor(VIEWtparent(fb));
     428       15557 :                                                                         BBPunfix(fb->batCacheid);
     429       15557 :                                                                         fb = nb;
     430       15557 :                                                                         if (fb == NULL) {
     431           0 :                                                                                 msg = createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column descriptor");
     432           0 :                                                                                 goto bailout;
     433             :                                                                         }
     434             :                                                                 }
     435             :                                                         }
     436             : 
     437       15557 :                                                         BATiter fbi = bat_iterator(fb);
     438       15557 :                                                         ssize_t (*tostr)(str*,size_t*,const void*,bool) = BATatoms[fbi.type].atomToStr;
     439       15557 :                                                         if (fbi.minpos != BUN_NONE) {
     440       15138 :                                                                 if (tostr(&buf, &buflen, BUNtail(fbi, fbi.minpos), false) < 0) {
     441           0 :                                                                         bat_iterator_end(&fbi);
     442           0 :                                                                         BBPunfix(fb->batCacheid);
     443           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     444           0 :                                                                         goto bailout;
     445             :                                                                 }
     446       15138 :                                                                 nval = buf;
     447             :                                                         } else {
     448             :                                                                 nval = (char *) str_nil;
     449             :                                                         }
     450       15557 :                                                         if (BUNappend(minval, nval, false) != GDK_SUCCEED) {
     451           0 :                                                                 bat_iterator_end(&fbi);
     452           0 :                                                                 BBPunfix(fb->batCacheid);
     453           0 :                                                                 goto bailout;
     454             :                                                         }
     455             : 
     456       15557 :                                                         if (fbi.maxpos != BUN_NONE) {
     457       15428 :                                                                 if (tostr(&buf, &buflen, BUNtail(fbi, fbi.maxpos), false) < 0) {
     458           0 :                                                                         bat_iterator_end(&fbi);
     459           0 :                                                                         BBPunfix(fb->batCacheid);
     460           0 :                                                                         msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     461           0 :                                                                         goto bailout;
     462             :                                                                 }
     463       15428 :                                                                 nval = buf;
     464             :                                                         } else {
     465             :                                                                 nval = (char *) str_nil;
     466             :                                                         }
     467       15557 :                                                         bat_iterator_end(&fbi);
     468       15557 :                                                         if (BUNappend(maxval, nval, false) != GDK_SUCCEED) {
     469           0 :                                                                 BBPunfix(fb->batCacheid);
     470           0 :                                                                 goto bailout;
     471             :                                                         }
     472       15557 :                                                         BBPunfix(fb->batCacheid);
     473       17494 :                                                 } else if (BUNappend(minval, str_nil, false) != GDK_SUCCEED || BUNappend(maxval, str_nil, false) != GDK_SUCCEED) {
     474           0 :                                                         bat_iterator_end(&posi);
     475           0 :                                                         BBPreclaim(re);
     476           0 :                                                         goto bailout;
     477       17494 :                                                 } else if (re) {
     478           0 :                                                         bat_iterator_end(&posi);
     479           0 :                                                         BBPunfix(re->batCacheid);
     480             :                                                 } else {
     481       17494 :                                                         bat_iterator_end(&posi);
     482             :                                                 }
     483             :                                         }
     484             :                                 }
     485             :                         }
     486             :                 }
     487             :         }
     488             : 
     489         152 :         GDKfree(buf);
     490         152 :         *rcid = cid->batCacheid;
     491         152 :         BBPkeepref(cid);
     492         152 :         *rsch = sch->batCacheid;
     493         152 :         BBPkeepref(sch);
     494         152 :         *rtab = tab->batCacheid;
     495         152 :         BBPkeepref(tab);
     496         152 :         *rcol = col->batCacheid;
     497         152 :         BBPkeepref(col);
     498         152 :         *rtype = type->batCacheid;
     499         152 :         BBPkeepref(type);
     500         152 :         *rwidth = width->batCacheid;
     501         152 :         BBPkeepref(width);
     502         152 :         *rcount = count->batCacheid;
     503         152 :         BBPkeepref(count);
     504         152 :         *runique = unique->batCacheid;
     505         152 :         BBPkeepref(unique);
     506         152 :         *rnils = nils->batCacheid;
     507         152 :         BBPkeepref(nils);
     508         152 :         *rminval = minval->batCacheid;
     509         152 :         BBPkeepref(minval);
     510         152 :         *rmaxval = maxval->batCacheid;
     511         152 :         BBPkeepref(maxval);
     512         152 :         *rsorted = sorted->batCacheid;
     513         152 :         BBPkeepref(sorted);
     514         152 :         *rrevsorted = revsorted->batCacheid;
     515         152 :         BBPkeepref(revsorted);
     516         152 :         return MAL_SUCCEED;
     517           0 : bailout:
     518           0 :         GDKfree(buf);
     519           0 :         BBPreclaim(cid);
     520           0 :         BBPreclaim(sch);
     521           0 :         BBPreclaim(tab);
     522           0 :         BBPreclaim(col);
     523           0 :         BBPreclaim(type);
     524           0 :         BBPreclaim(width);
     525           0 :         BBPreclaim(count);
     526           0 :         BBPreclaim(unique);
     527           0 :         BBPreclaim(nils);
     528           0 :         BBPreclaim(minval);
     529           0 :         BBPreclaim(maxval);
     530           0 :         BBPreclaim(sorted);
     531           0 :         BBPreclaim(revsorted);
     532           0 :         if (!msg)
     533           0 :                 msg = createException(SQL, "sql.statistics", GDK_EXCEPTION);
     534             :         return msg;
     535             : }

Generated by: LCOV version 1.14