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 44 : sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
82 : {
83 44 : mvc *m = NULL;
84 44 : sql_trans *tr = NULL;
85 44 : str sch = NULL, tbl = NULL, col = NULL, msg = MAL_SUCCEED;
86 44 : int argc = pci->argc, sfnd = 0, tfnd = 0, cfnd = 0;
87 :
88 44 : if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
89 : return msg;
90 44 : if ((msg = checkSQLContext(cntxt)) != NULL)
91 : return msg;
92 :
93 44 : tr = m->session->tr;
94 44 : 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 39 : tbl = *getArgReference_str(stk, pci, 2);
102 39 : if (strNil(tbl))
103 0 : throw(SQL, "sql.analyze", SQLSTATE(42000) "Table name cannot be NULL");
104 : /* fall through */
105 : case 2:
106 44 : sch = *getArgReference_str(stk, pci, 1);
107 44 : if (strNil(sch))
108 0 : throw(SQL, "sql.analyze", SQLSTATE(42000) "Schema name cannot be NULL");
109 : }
110 :
111 44 : 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 44 : struct os_iter si;
115 44 : os_iterator(&si, tr->cat->schemas, tr, NULL);
116 355 : for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
117 312 : sql_schema *s = (sql_schema *)b;
118 312 : if (s->base.name[0] == '%')
119 269 : continue;
120 :
121 268 : if (sch && strcmp(s->base.name, sch))
122 225 : continue;
123 43 : sfnd = 1;
124 43 : struct os_iter oi;
125 43 : os_iterator(&oi, s->tables, tr, NULL);
126 5165 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
127 5123 : sql_table *t = (sql_table *)b;
128 :
129 5123 : if (tbl && strcmp(t->base.name, tbl))
130 4832 : continue;
131 329 : tfnd = 1;
132 39 : 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 290 : 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 290 : if (isTable(t) && ol_first_node(t->columns)) {
138 604 : for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
139 487 : sql_column *c = (sql_column *) ncol->data;
140 :
141 487 : if (col && strcmp(c->base.name, col))
142 18 : continue;
143 469 : cfnd = 1;
144 469 : 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 43 : if (sch && !sfnd)
152 1 : throw(SQL, "sql.analyze", SQLSTATE(3F000) "Schema '%s' does not exist", sch);
153 42 : if (tbl && !tfnd)
154 0 : throw(SQL, "sql.analyze", SQLSTATE(42S02) "Table '%s' does not exist", tbl);
155 42 : if (col && !cfnd)
156 0 : throw(SQL, "sql.analyze", SQLSTATE(38000) "Column '%s' does not exist", col);
157 :
158 42 : sqlstore *store = tr->store;
159 42 : os_iterator(&si, tr->cat->schemas, tr, NULL);
160 339 : for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
161 297 : sql_schema *s = (sql_schema *)b;
162 297 : if (b->name[0] == '%')
163 255 : continue;
164 :
165 255 : if (sch && strcmp(sch, b->name))
166 213 : continue;
167 42 : struct os_iter oi;
168 42 : os_iterator(&oi, s->tables, tr, NULL);
169 5164 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
170 5122 : sql_table *t = (sql_table *) b;
171 :
172 5122 : if (tbl && strcmp(b->name, tbl))
173 4832 : continue;
174 290 : if (isTable(t) && ol_first_node(t->columns)) {
175 604 : for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
176 487 : sql_column *c = (sql_column *) ncol->data;
177 487 : BAT *b, *unq;
178 487 : ptr mn, mx;
179 :
180 487 : if (col && strcmp(c->base.name, col))
181 18 : continue;
182 :
183 469 : int access = c->storage_type && c->storage_type[0] == 'D' ? RD_EXT : RDONLY;
184 469 : 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 469 : if (isVIEW(b)) { /* If it is a view get the parent BAT */
187 468 : BAT *nb = BATdescriptor(VIEWtparent(b));
188 468 : BBPunfix(b->batCacheid);
189 468 : b = nb;
190 468 : if (b == NULL)
191 0 : continue;
192 : }
193 :
194 : /* Collect new sorted and revsorted properties */
195 469 : (void) BATordered(b);
196 469 : (void) BATordered_rev(b);
197 :
198 : /* Check for nils existence */
199 469 : (void) BATcount_no_nil(b, NULL);
200 :
201 : /* Test if column is unique */
202 469 : if ((unq = BATunique(b, NULL)))
203 469 : BBPunfix(unq->batCacheid);
204 :
205 : /* Guess number of uniques if not entirely unique */
206 469 : (void) BATguess_uniques(b, NULL);
207 :
208 : /* Collect min and max values */
209 469 : mn = BATmin(b, NULL);
210 469 : GDKfree(mn);
211 469 : mx = BATmax(b, NULL);
212 469 : GDKfree(mx);
213 469 : BBPunfix(b->batCacheid);
214 : }
215 : }
216 : }
217 : }
218 : return MAL_SUCCEED;
219 : }
220 :
221 : str
222 155 : sql_statistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
223 : {
224 155 : BAT *cid, *sch, *tab, *col, *type, *width, *count, *unique, *nils, *minval, *maxval, *sorted, *revsorted;
225 155 : mvc *m = NULL;
226 155 : sql_trans *tr = NULL;
227 155 : sqlstore *store = NULL;
228 155 : bat *rcid = getArgReference_bat(stk, pci, 0);
229 155 : bat *rsch = getArgReference_bat(stk, pci, 1);
230 155 : bat *rtab = getArgReference_bat(stk, pci, 2);
231 155 : bat *rcol = getArgReference_bat(stk, pci, 3);
232 155 : bat *rtype = getArgReference_bat(stk, pci, 4);
233 155 : bat *rwidth = getArgReference_bat(stk, pci, 5);
234 155 : bat *rcount = getArgReference_bat(stk, pci, 6);
235 155 : bat *runique = getArgReference_bat(stk, pci, 7);
236 155 : bat *rnils = getArgReference_bat(stk, pci, 8);
237 155 : bat *rminval = getArgReference_bat(stk, pci, 9);
238 155 : bat *rmaxval = getArgReference_bat(stk, pci, 10);
239 155 : bat *rsorted = getArgReference_bat(stk, pci, 11);
240 155 : bat *rrevsorted = getArgReference_bat(stk, pci, 12);
241 155 : str sname = NULL, tname = NULL, cname = NULL, msg = MAL_SUCCEED;
242 155 : struct os_iter si = {0};
243 155 : BUN nrows = 0;
244 155 : int sfnd = 0, tfnd = 0, cfnd = 0;
245 155 : size_t buflen = 0;
246 155 : char *buf = NULL, *nval = NULL;
247 :
248 155 : if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
249 : return msg;
250 155 : if ((msg = checkSQLContext(cntxt)) != NULL)
251 : return msg;
252 :
253 155 : 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 155 : 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 155 : 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 155 : tr = m->session->tr;
270 155 : store = tr->store;
271 : /* Do all the validations before retrieving any statistics */
272 155 : os_iterator(&si, tr->cat->schemas, tr, NULL);
273 1229 : for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
274 1076 : sql_schema *s = (sql_schema *)b;
275 1076 : if (s->base.name[0] == '%')
276 183 : continue;
277 :
278 923 : if (sname && strcmp(s->base.name, sname))
279 30 : continue;
280 893 : sfnd = 1;
281 893 : struct os_iter oi;
282 893 : os_iterator(&oi, s->tables, tr, NULL);
283 22537 : for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
284 21646 : sql_table *t = (sql_table *)b;
285 :
286 21646 : if (tname && strcmp(t->base.name, tname))
287 744 : continue;
288 20908 : 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 20902 : 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 20902 : if (isTable(t) && ol_first_node(t->columns)) {
295 39793 : for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
296 33303 : sql_column *c = (sql_column *) ncol->data;
297 :
298 33303 : if (cname && strcmp(c->base.name, cname))
299 0 : continue;
300 33303 : cfnd = 1;
301 33303 : nrows++;
302 33303 : 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 153 : if (sname && !sfnd)
310 0 : throw(SQL, "sql.statistics", SQLSTATE(3F000) "Schema '%s' does not exist", sname);
311 153 : if (tname && !tfnd)
312 0 : throw(SQL, "sql.statistics", SQLSTATE(42S02) "Table '%s' does not exist", tname);
313 153 : if (cname && !cfnd)
314 0 : throw(SQL, "sql.statistics", SQLSTATE(38000) "Column '%s' does not exist", cname);
315 :
316 153 : cid = COLnew(0, TYPE_int, nrows, TRANSIENT);
317 153 : sch = COLnew(0, TYPE_str, nrows, TRANSIENT);
318 153 : tab = COLnew(0, TYPE_str, nrows, TRANSIENT);
319 153 : col = COLnew(0, TYPE_str, nrows, TRANSIENT);
320 153 : type = COLnew(0, TYPE_str, nrows, TRANSIENT);
321 153 : width = COLnew(0, TYPE_int, nrows, TRANSIENT);
322 153 : count = COLnew(0, TYPE_lng, nrows, TRANSIENT);
323 153 : unique = COLnew(0, TYPE_bit, nrows, TRANSIENT);
324 153 : nils = COLnew(0, TYPE_bit, nrows, TRANSIENT);
325 153 : minval = COLnew(0, TYPE_str, nrows, TRANSIENT);
326 153 : maxval = COLnew(0, TYPE_str, nrows, TRANSIENT);
327 153 : sorted = COLnew(0, TYPE_bit, nrows, TRANSIENT);
328 153 : revsorted = COLnew(0, TYPE_bit, nrows, TRANSIENT);
329 :
330 153 : 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 153 : si = (struct os_iter) {0};
336 153 : os_iterator(&si, tr->cat->schemas, tr, NULL);
337 1227 : for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
338 1074 : sql_schema *s = (sql_schema *) b;
339 1074 : if ((sname && strcmp(b->name, sname)) || b->name[0] == '%')
340 183 : continue;
341 891 : if (s->tables) {
342 891 : struct os_iter oi;
343 :
344 891 : os_iterator(&oi, s->tables, tr, NULL);
345 22535 : for (sql_base *bt = oi_next(&oi); bt; bt = oi_next(&oi)) {
346 21644 : sql_table *t = (sql_table *) bt;
347 21644 : if (tname && strcmp(bt->name, tname))
348 744 : continue;
349 20900 : if (isTable(t) && ol_first_node(t->columns)) {
350 39791 : for (node *ncol = ol_first_node((t)->columns); ncol; ncol = ncol->next) {
351 33301 : sql_column *c = (sql_column *) ncol->data;
352 33301 : int w;
353 33301 : lng cnt;
354 33301 : bit un, hnils, issorted, isrevsorted, dict;
355 33301 : BAT *qd = NULL, *fb = NULL, *re = NULL;
356 :
357 33301 : if (cname && strcmp(c->base.name, cname))
358 0 : continue;
359 :
360 33301 : 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 33301 : BATiter qdi = bat_iterator(qd);
365 33301 : BATiter posi;
366 33301 : 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 33301 : issorted = qdi.sorted;
391 33301 : isrevsorted = qdi.revsorted;
392 33301 : hnils = !qdi.nonil || qdi.nil;
393 33301 : posi = bat_iterator_copy(&qdi);
394 : }
395 :
396 33301 : w = qdi.width;
397 33301 : cnt = qdi.count;
398 33301 : un = qdi.key;
399 33301 : bat_iterator_end(&qdi);
400 :
401 66602 : if (BUNappend(cid, &c->base.id, false) != GDK_SUCCEED ||
402 66602 : BUNappend(sch, b->name, false) != GDK_SUCCEED ||
403 66602 : BUNappend(tab, bt->name, false) != GDK_SUCCEED ||
404 66602 : BUNappend(col, c->base.name, false) != GDK_SUCCEED ||
405 66602 : BUNappend(type, c->type.type->base.name, false) != GDK_SUCCEED ||
406 66602 : BUNappend(width, &w, false) != GDK_SUCCEED ||
407 66602 : BUNappend(count, &cnt, false) != GDK_SUCCEED ||
408 66602 : BUNappend(unique, &un, false) != GDK_SUCCEED ||
409 66602 : BUNappend(nils, &hnils, false) != GDK_SUCCEED ||
410 66602 : BUNappend(sorted, &issorted, false) != GDK_SUCCEED ||
411 33301 : BUNappend(revsorted, &isrevsorted, false) != GDK_SUCCEED) {
412 0 : bat_iterator_end(&posi);
413 0 : BBPreclaim(re);
414 0 : goto bailout;
415 : }
416 :
417 48958 : if (posi.minpos != BUN_NONE || posi.maxpos != BUN_NONE) {
418 15657 : bat_iterator_end(&posi);
419 15657 : if (dict) {
420 : fb = re;
421 : } else {
422 15657 : 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 15657 : if (isVIEW(fb)) { /* If it is a view get the parent BAT */
427 15657 : BAT *nb = BATdescriptor(VIEWtparent(fb));
428 15657 : BBPunfix(fb->batCacheid);
429 15657 : fb = nb;
430 15657 : 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 15657 : BATiter fbi = bat_iterator(fb);
438 15657 : ssize_t (*tostr)(str*,size_t*,const void*,bool) = BATatoms[fbi.type].atomToStr;
439 15657 : if (fbi.minpos != BUN_NONE) {
440 15312 : 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 15312 : nval = buf;
447 : } else {
448 : nval = (char *) str_nil;
449 : }
450 15657 : 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 15657 : if (fbi.maxpos != BUN_NONE) {
457 15522 : 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 15522 : nval = buf;
464 : } else {
465 : nval = (char *) str_nil;
466 : }
467 15657 : bat_iterator_end(&fbi);
468 15657 : if (BUNappend(maxval, nval, false) != GDK_SUCCEED) {
469 0 : BBPunfix(fb->batCacheid);
470 0 : goto bailout;
471 : }
472 15657 : BBPunfix(fb->batCacheid);
473 17644 : } 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 17644 : } else if (re) {
478 0 : bat_iterator_end(&posi);
479 0 : BBPunfix(re->batCacheid);
480 : } else {
481 17644 : bat_iterator_end(&posi);
482 : }
483 : }
484 : }
485 : }
486 : }
487 : }
488 :
489 153 : GDKfree(buf);
490 153 : *rcid = cid->batCacheid;
491 153 : BBPkeepref(cid);
492 153 : *rsch = sch->batCacheid;
493 153 : BBPkeepref(sch);
494 153 : *rtab = tab->batCacheid;
495 153 : BBPkeepref(tab);
496 153 : *rcol = col->batCacheid;
497 153 : BBPkeepref(col);
498 153 : *rtype = type->batCacheid;
499 153 : BBPkeepref(type);
500 153 : *rwidth = width->batCacheid;
501 153 : BBPkeepref(width);
502 153 : *rcount = count->batCacheid;
503 153 : BBPkeepref(count);
504 153 : *runique = unique->batCacheid;
505 153 : BBPkeepref(unique);
506 153 : *rnils = nils->batCacheid;
507 153 : BBPkeepref(nils);
508 153 : *rminval = minval->batCacheid;
509 153 : BBPkeepref(minval);
510 153 : *rmaxval = maxval->batCacheid;
511 153 : BBPkeepref(maxval);
512 153 : *rsorted = sorted->batCacheid;
513 153 : BBPkeepref(sorted);
514 153 : *rrevsorted = revsorted->batCacheid;
515 153 : BBPkeepref(revsorted);
516 153 : 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 : }
|