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 : }
|