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 : /*
14 : * (c) Martin Kersten, Sjoerd Mullender
15 : * Series generating module for integer, decimal, real, double and timestamps.
16 : */
17 :
18 : #include "monetdb_config.h"
19 : #include "opt_prelude.h"
20 : #include "generator.h"
21 : #include "gdk_time.h"
22 :
23 :
24 : #define IDENTITY(x) (x)
25 :
26 : /*
27 : * The noop simply means that we keep the properties for the generator object.
28 : */
29 : #define VLTnoop(TPE) \
30 : do { \
31 : TPE s; \
32 : s = pci->argc == 3 ? 1: *getArgReference_##TPE(stk,pci, 3); \
33 : zeroerror = (s == 0); \
34 : nullerr = is_##TPE##_nil(s); \
35 : } while (0)
36 :
37 : str
38 207 : VLTgenerator_noop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
39 : {
40 207 : int nullerr= 0, zeroerror=0, tpe;
41 207 : (void) cntxt;
42 :
43 207 : switch( tpe = getArgType(mb,pci,1)){
44 107 : case TYPE_bte: VLTnoop(bte); break;
45 19 : case TYPE_sht: VLTnoop(sht); break;
46 29 : case TYPE_int: VLTnoop(int); break;
47 10 : case TYPE_lng: VLTnoop(lng); break;
48 : #ifdef HAVE_HGE
49 5 : case TYPE_hge: VLTnoop(hge); break;
50 : #endif
51 3 : case TYPE_flt: VLTnoop(flt); break;
52 7 : case TYPE_dbl: VLTnoop(dbl); break;
53 27 : default:
54 27 : if (tpe == TYPE_timestamp){
55 : /* with timestamp, step is of SQL type "interval seconds",
56 : * i.e., MAL / C type "lng" */
57 27 : VLTnoop(lng);
58 0 : } else throw(MAL,"generator.noop", SQLSTATE(42000) "unknown data type %d", getArgType(mb,pci,1));
59 : }
60 207 : if( zeroerror)
61 2 : throw(MAL,"generator.noop", SQLSTATE(42000) "Zero step size not allowed");
62 205 : if( nullerr)
63 2 : throw(MAL,"generator.noop", SQLSTATE(42000) "Null step size not allowed");
64 : return MAL_SUCCEED;
65 : }
66 :
67 : /*
68 : * The base line consists of materializing the generator iterator value
69 : */
70 : #define VLTmaterialize(TPE) \
71 : do { \
72 : TPE *v, f, l, s; \
73 : f = *getArgReference_##TPE(stk, pci, 1); \
74 : l = *getArgReference_##TPE(stk, pci, 2); \
75 : if ( pci->argc == 3) \
76 : s = f<l? (TPE) 1: (TPE)-1; \
77 : else s = *getArgReference_##TPE(stk,pci, 3); \
78 : if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) \
79 : throw(MAL, "generator.table", \
80 : SQLSTATE(42000) "Illegal generator range"); \
81 : n = (BUN) ((l - f) / s); \
82 : if ((TPE) (n * s + f) != l) \
83 : n++; \
84 : bn = COLnew(0, TYPE_##TPE, n, TRANSIENT); \
85 : if (bn == NULL) \
86 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
87 : v = (TPE*) Tloc(bn, 0); \
88 : for (c = 0; c < n; c++) \
89 : *v++ = (TPE) (f + c * s); \
90 : bn->tsorted = s > 0 || n <= 1; \
91 : bn->trevsorted = s < 0 || n <= 1; \
92 : } while (0)
93 :
94 : static str
95 178 : VLTgenerator_table_(BAT **result, Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
96 : {
97 178 : BUN c, n;
98 178 : BAT *bn;
99 178 : int tpe;
100 178 : (void) cntxt;
101 :
102 178 : *result = NULL;
103 178 : tpe = getArgType(mb, pci, 1);
104 178 : switch (tpe) {
105 92 : case TYPE_bte:
106 1730 : VLTmaterialize(bte);
107 76 : break;
108 19 : case TYPE_sht:
109 67397 : VLTmaterialize(sht);
110 17 : break;
111 29 : case TYPE_int:
112 118836489 : VLTmaterialize(int);
113 26 : break;
114 8 : case TYPE_lng:
115 34 : VLTmaterialize(lng);
116 4 : break;
117 : #ifdef HAVE_HGE
118 5 : case TYPE_hge:
119 616 : VLTmaterialize(hge);
120 4 : break;
121 : #endif
122 2 : case TYPE_flt:
123 17 : VLTmaterialize(flt);
124 2 : break;
125 5 : case TYPE_dbl:
126 42 : VLTmaterialize(dbl);
127 5 : break;
128 18 : default:
129 18 : if (tpe == TYPE_timestamp) {
130 18 : timestamp *v,f,l;
131 18 : lng s;
132 18 : ValRecord ret;
133 18 : if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
134 18 : &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
135 0 : throw(MAL, "generator.table",
136 : SQLSTATE(42000) "Illegal generator expression range");
137 18 : f = *getArgReference_TYPE(stk, pci, 1, timestamp);
138 18 : l = *getArgReference_TYPE(stk, pci, 2, timestamp);
139 18 : if ( pci->argc == 3)
140 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
141 18 : s = *getArgReference_lng(stk, pci, 3);
142 18 : if (s == 0 ||
143 18 : (s > 0 && ret.val.btval > 0) ||
144 10 : (s < 0 && ret.val.btval < 0) ||
145 18 : is_timestamp_nil(f) || is_timestamp_nil(l))
146 0 : throw(MAL, "generator.table",
147 : SQLSTATE(42000) "Illegal generator range");
148 : /* casting one value to lng causes the whole
149 : * computation to be done as lng, reducing the
150 : * risk of overflow */
151 18 : s *= 1000; /* msec -> usec */
152 18 : n = (BUN) (timestamp_diff(l, f) / s);
153 18 : bn = COLnew(0, TYPE_timestamp, n + 1, TRANSIENT);
154 18 : if (bn == NULL)
155 0 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
156 18 : v = (timestamp *) Tloc(bn, 0);
157 161 : for (c = 0; c < n; c++) {
158 143 : *v++ = f;
159 143 : f = timestamp_add_usec(f, s);
160 143 : if (is_timestamp_nil(f)) {
161 0 : BBPreclaim(bn);
162 0 : throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
163 : }
164 : }
165 18 : if (f != l) {
166 9 : *v++ = f;
167 9 : n++;
168 : }
169 18 : bn->tsorted = s > 0 || n <= 1;
170 18 : bn->trevsorted = s < 0 || n <= 1;
171 : } else {
172 0 : throw(MAL, "generator.table", SQLSTATE(42000) "Unsupported type");
173 : }
174 18 : break;
175 : }
176 152 : BATsetcount(bn, c);
177 152 : bn->tkey = true;
178 152 : bn->tnil = false;
179 152 : bn->tnonil = true;
180 152 : *result = bn;
181 152 : return MAL_SUCCEED;
182 : }
183 :
184 : str
185 182 : VLTgenerator_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
186 : {
187 182 : str msg;
188 182 : BAT *bn = NULL;
189 :
190 182 : if ((msg = VLTgenerator_noop(cntxt, mb, stk, pci)) != MAL_SUCCEED)
191 : return msg;
192 :
193 178 : msg = VLTgenerator_table_(&bn, cntxt, mb, stk, pci);
194 178 : if( msg == MAL_SUCCEED){
195 152 : *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
196 152 : BBPkeepref(bn);
197 : }
198 : return msg;
199 : }
200 :
201 : /*
202 : * Selection over the generator table does not require a materialization of the table
203 : * An optimizer can replace the subselect directly into a generator specific one.
204 : * The target to look for is generator.series(A1,A2,A3)
205 : * We need the generator parameters, which are injected to replace the target column
206 : */
207 : static InstrPtr
208 157 : findGeneratorDefinition(MalBlkPtr mb, InstrPtr pci, int target)
209 : {
210 157 : InstrPtr q, p = NULL;
211 157 : int i;
212 :
213 2285 : for (i = 1; i < mb->stop; i++) {
214 2285 : q = getInstrPtr(mb, i);
215 2285 : if (q->argv[0] == target && getModuleId(q) == generatorRef && (getFunctionId(q) == parametersRef || getFunctionId(q) == seriesRef))
216 2285 : p = q;
217 2285 : if (q == pci)
218 157 : return p;
219 : }
220 : return p;
221 : }
222 :
223 : #define calculate_range(TPE, TPE2) \
224 : do { \
225 : TPE f, l, s, low, hgh; \
226 : \
227 : f = * getArgReference_##TPE(stk, p, 1); \
228 : l = * getArgReference_##TPE(stk, p, 2); \
229 : if ( p->argc == 3) \
230 : s = f<l? (TPE) 1: (TPE)-1; \
231 : else s = * getArgReference_##TPE(stk, p, 3); \
232 : if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) { \
233 : BBPreclaim(cand); \
234 : throw(MAL, "generator.select", \
235 : SQLSTATE(42000) "Illegal generator range"); \
236 : } \
237 : n = (BUN) (((TPE2) l - (TPE2) f) / (TPE2) s); \
238 : if ((TPE)(n * s + f) != l) \
239 : n++; \
240 : \
241 : low = * getArgReference_##TPE(stk, pci, i); \
242 : hgh = * getArgReference_##TPE(stk, pci, i + 1); \
243 : \
244 : if (!is_##TPE##_nil(low) && low == hgh) \
245 : hi = li; \
246 : if (is_##TPE##_nil(low) && is_##TPE##_nil(hgh)) { \
247 : if (li && hi && !anti) { \
248 : /* match NILs (of which there aren't */ \
249 : /* any) */ \
250 : o1 = o2 = 0; \
251 : } else { \
252 : /* match all non-NIL values, */ \
253 : /* i.e. everything */ \
254 : o1 = 0; \
255 : o2 = (oid) n; \
256 : } \
257 : } else if (s > 0) { \
258 : if (is_##TPE##_nil(low) || low < f) \
259 : o1 = 0; \
260 : else { \
261 : o1 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s); \
262 : if ((TPE) (f + o1 * s) < low || \
263 : (!li && (TPE) (f + o1 * s) == low)) \
264 : o1++; \
265 : } \
266 : if (is_##TPE##_nil(hgh)) \
267 : o2 = (oid) n; \
268 : else if (hgh < f) \
269 : o2 = 0; \
270 : else { \
271 : o2 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s); \
272 : if ((hi && (TPE) (f + o2 * s) == hgh) || \
273 : (TPE) (f + o2 * s) < hgh) \
274 : o2++; \
275 : } \
276 : } else { \
277 : if (is_##TPE##_nil(low)) \
278 : o2 = (oid) n; \
279 : else if (low > f) \
280 : o2 = 0; \
281 : else { \
282 : o2 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s); \
283 : if ((li && (TPE) (f + o2 * s) == low) || \
284 : (TPE) (f + o2 * s) > low) \
285 : o2++; \
286 : } \
287 : if (is_##TPE##_nil(hgh) || hgh > f) \
288 : o1 = 0; \
289 : else { \
290 : o1 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s); \
291 : if ((!hi && (TPE) (f + o1 * s) == hgh) || \
292 : (TPE) (f + o1 * s) > hgh) \
293 : o1++; \
294 : } \
295 : } \
296 : } while (0)
297 :
298 : str
299 0 : VLTgenerator_subselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
300 : {
301 0 : bit li, hi, anti;
302 0 : int i;
303 0 : oid o1, o2;
304 0 : BUN n = 0;
305 0 : BAT *bn, *cand = NULL;
306 0 : struct canditer ci = (struct canditer) {.tpe = cand_dense};
307 0 : InstrPtr p;
308 0 : int tpe;
309 :
310 0 : (void) cntxt;
311 0 : p = findGeneratorDefinition(mb, pci, pci->argv[1]);
312 0 : if (p == NULL)
313 0 : throw(MAL, "generator.select",
314 : SQLSTATE(42000) "Could not locate definition for object");
315 :
316 0 : if (pci->argc == 8) { /* candidate list included */
317 0 : bat candid = *getArgReference_bat(stk, pci, 2);
318 0 : if (candid) {
319 0 : cand = BATdescriptor(candid);
320 0 : if (cand == NULL)
321 0 : throw(MAL, "generator.select",
322 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
323 0 : canditer_init(&ci, NULL, cand);
324 : }
325 : i = 3;
326 : } else
327 : i = 2;
328 :
329 0 : li = * getArgReference_bit(stk, pci, i + 2);
330 0 : hi = * getArgReference_bit(stk, pci, i + 3);
331 0 : anti = * getArgReference_bit(stk, pci, i + 4);
332 :
333 0 : switch ( tpe = getArgType(mb, pci, i)) {
334 0 : case TYPE_bte: calculate_range(bte, sht); break;
335 0 : case TYPE_sht: calculate_range(sht, int); break;
336 0 : case TYPE_int: calculate_range(int, lng); break;
337 : #ifndef HAVE_HGE
338 : case TYPE_lng: calculate_range(lng, lng); break;
339 : #else
340 0 : case TYPE_lng: calculate_range(lng, hge); break;
341 0 : case TYPE_hge: calculate_range(hge, hge); break;
342 : #endif
343 0 : case TYPE_flt: calculate_range(flt, dbl); break;
344 0 : case TYPE_dbl: calculate_range(dbl, dbl); break;
345 0 : default:
346 0 : if( tpe == TYPE_timestamp){
347 0 : timestamp tsf,tsl;
348 0 : timestamp tlow,thgh;
349 0 : lng tss;
350 0 : oid *ol;
351 :
352 0 : tsf = *getArgReference_TYPE(stk, p, 1, timestamp);
353 0 : tsl = *getArgReference_TYPE(stk, p, 2, timestamp);
354 0 : if ( p->argc == 3) {
355 0 : BBPreclaim(cand);
356 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
357 : }
358 0 : tss = *getArgReference_lng(stk, p, 3);
359 0 : if ( tss == 0 ||
360 0 : is_timestamp_nil(tsf) || is_timestamp_nil(tsl) ||
361 0 : (tss > 0 && tsf > tsl ) ||
362 0 : (tss < 0 && tsf < tsl )
363 : ) {
364 0 : BBPreclaim(cand);
365 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
366 : }
367 :
368 0 : tlow = *getArgReference_TYPE(stk,pci,i, timestamp);
369 0 : thgh = *getArgReference_TYPE(stk,pci,i+1, timestamp);
370 :
371 0 : if (!is_timestamp_nil(tlow) && tlow == thgh)
372 0 : hi = li;
373 0 : if( hi && !is_timestamp_nil(thgh)) {
374 0 : thgh = timestamp_add_usec(thgh, 1);
375 0 : if (is_timestamp_nil(thgh)) {
376 0 : BBPreclaim(cand);
377 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
378 : }
379 : }
380 0 : if( !li && !is_timestamp_nil(tlow)) {
381 0 : tlow = timestamp_add_usec(tlow, 1);
382 0 : if (is_timestamp_nil(tlow)) {
383 0 : BBPreclaim(cand);
384 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
385 : }
386 : }
387 :
388 : /* casting one value to lng causes the whole
389 : * computation to be done as lng, reducing the
390 : * risk of overflow */
391 0 : tss *= 1000; /* msec -> usec */
392 0 : o2 = (BUN) (timestamp_diff(tsl, tsf) / tss);
393 0 : bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
394 0 : if (bn == NULL) {
395 0 : BBPreclaim(cand);
396 0 : throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
397 : }
398 :
399 : // simply enumerate the sequence and filter it by predicate and candidate list
400 0 : ol = (oid *) Tloc(bn, 0);
401 0 : for (o1=0; o1 <= o2; o1++) {
402 0 : if(((is_timestamp_nil(tlow) || tsf >= tlow) &&
403 0 : (is_timestamp_nil(thgh) || tsf < thgh)) != anti ){
404 : /* could be improved when no candidate list is available into a void/void BAT */
405 0 : if( cand == NULL || canditer_contains(&ci, o1)) {
406 0 : *ol++ = o1;
407 0 : n++;
408 : }
409 : }
410 0 : tsf = timestamp_add_usec(tsf, tss);
411 0 : if (is_timestamp_nil(tsf)) {
412 0 : BBPreclaim(cand);
413 0 : BBPreclaim(bn);
414 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
415 : }
416 : }
417 0 : BBPreclaim(cand);
418 0 : BATsetcount(bn, n);
419 0 : bn->tsorted = true;
420 0 : bn->trevsorted = BATcount(bn) <= 1;
421 0 : bn->tkey = true;
422 0 : bn->tnil = false;
423 0 : bn->tnonil = true;
424 0 : * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
425 0 : BBPkeepref(bn);
426 0 : return MAL_SUCCEED;
427 : } else {
428 0 : BBPreclaim(cand);
429 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Unsupported type in select");
430 : }
431 : }
432 0 : if (o1 > (oid) n)
433 : o1 = (oid) n;
434 0 : if (o2 > (oid) n)
435 : o2 = (oid) n;
436 0 : assert(o1 <= o2);
437 0 : assert(o2 - o1 <= (oid) n);
438 0 : if (anti && o1 == o2) {
439 0 : o1 = 0;
440 0 : o2 = (oid) n;
441 0 : anti = 0;
442 : }
443 0 : if (cand) {
444 0 : if (anti) {
445 0 : bn = canditer_slice2val(&ci, oid_nil, o1, o2, oid_nil);
446 : } else {
447 0 : bn = canditer_sliceval(&ci, o1, o2);
448 : }
449 0 : BBPunfix(cand->batCacheid);
450 0 : if (bn == NULL)
451 0 : throw(MAL, "generator.select",
452 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
453 : } else {
454 0 : if (anti) {
455 0 : oid o;
456 0 : oid *op;
457 :
458 0 : bn = COLnew(0, TYPE_oid, n - (o2 - o1), TRANSIENT);
459 0 : if (bn == NULL)
460 0 : throw(MAL, "generator.select",
461 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
462 0 : BATsetcount(bn, n - (o2 - o1));
463 0 : op = (oid *) Tloc(bn, 0);
464 0 : for (o = 0; o < o1; o++)
465 0 : *op++ = o;
466 0 : for (o = o2; o < (oid) n; o++)
467 0 : *op++ = o;
468 0 : bn->tnil = false;
469 0 : bn->tnonil = true;
470 0 : bn->tsorted = true;
471 0 : bn->trevsorted = BATcount(bn) <= 1;
472 0 : bn->tkey = true;
473 : } else {
474 0 : bn = BATdense(0, o1, (BUN) (o2 - o1));
475 0 : if (bn == NULL)
476 0 : throw(MAL, "generator.select",
477 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
478 : }
479 : }
480 0 : * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
481 0 : BBPkeepref(bn);
482 0 : return MAL_SUCCEED;
483 : }
484 :
485 : #define PREVVALUEbte(x) ((x) - 1)
486 : #define PREVVALUEsht(x) ((x) - 1)
487 : #define PREVVALUEint(x) ((x) - 1)
488 : #define PREVVALUElng(x) ((x) - 1)
489 : #ifdef HAVE_HGE
490 : #define PREVVALUEhge(x) ((x) - 1)
491 : #endif
492 : #define PREVVALUEoid(x) ((x) - 1)
493 : #define PREVVALUEflt(x) nextafterf((x), -GDK_flt_max)
494 : #define PREVVALUEdbl(x) nextafter((x), -GDK_dbl_max)
495 :
496 : #define NEXTVALUEbte(x) ((x) + 1)
497 : #define NEXTVALUEsht(x) ((x) + 1)
498 : #define NEXTVALUEint(x) ((x) + 1)
499 : #define NEXTVALUElng(x) ((x) + 1)
500 : #ifdef HAVE_HGE
501 : #define NEXTVALUEhge(x) ((x) + 1)
502 : #endif
503 : #define NEXTVALUEoid(x) ((x) + 1)
504 : #define NEXTVALUEflt(x) nextafterf((x), GDK_flt_max)
505 : #define NEXTVALUEdbl(x) nextafter((x), GDK_dbl_max)
506 :
507 : #define HGE_ABS(a) (((a) < 0) ? -(a) : (a))
508 :
509 : #define VLTthetasubselect(TPE,ABS) \
510 : do { \
511 : TPE f,l,s, low, hgh; \
512 : BUN j; oid *v; \
513 : f = *getArgReference_##TPE(stk,p, 1); \
514 : l = *getArgReference_##TPE(stk,p, 2); \
515 : if ( p->argc == 3) \
516 : s = f<l? (TPE) 1: (TPE)-1; \
517 : else s = *getArgReference_##TPE(stk,p, 3); \
518 : if( s == 0 || (f<l && s < 0) || (f>l && s> 0)) { \
519 : BBPreclaim(cand); \
520 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal range"); \
521 : } \
522 : cap = (BUN)(ABS(l-f)/ABS(s)); \
523 : bn = COLnew(0, TYPE_oid, cap, TRANSIENT); \
524 : if( bn == NULL) { \
525 : BBPreclaim(cand); \
526 : throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
527 : } \
528 : low= hgh = TPE##_nil; \
529 : v = (oid*) Tloc(bn,0); \
530 : if ( strcmp(oper,"<") == 0){ \
531 : hgh= *getArgReference_##TPE(stk,pci,3); \
532 : hgh = PREVVALUE##TPE(hgh); \
533 : } else if ( strcmp(oper,"<=") == 0){ \
534 : hgh= *getArgReference_##TPE(stk,pci,3); \
535 : } else if ( strcmp(oper,">") == 0){ \
536 : low= *getArgReference_##TPE(stk,pci,3); \
537 : low = NEXTVALUE##TPE(low); \
538 : } else if ( strcmp(oper,">=") == 0){ \
539 : low= *getArgReference_##TPE(stk,pci,3); \
540 : } else if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){ \
541 : hgh= low= *getArgReference_##TPE(stk,pci,3); \
542 : anti = 1; \
543 : } else if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){ \
544 : hgh= low= *getArgReference_##TPE(stk,pci,3); \
545 : } else { \
546 : BBPreclaim(cand); \
547 : BBPreclaim(bn); \
548 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator"); \
549 : } \
550 : for(j=0;j<cap;j++, f+=s, o++) \
551 : if( ((is_##TPE##_nil(low) || f >= low) && (is_##TPE##_nil(hgh) || f <= hgh)) != anti){ \
552 : if(cand == NULL || canditer_contains(&ci, o)) { \
553 : *v++ = o; \
554 : c++; \
555 : } \
556 : } \
557 : } while (0)
558 :
559 :
560 27 : str VLTgenerator_thetasubselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
561 : {
562 27 : int anti =0,tpe;
563 27 : bat cndid =0;
564 27 : BAT *cand = 0, *bn = NULL;
565 27 : struct canditer ci = (struct canditer) {.tpe = cand_dense};
566 27 : BUN cap,j, c = 0;
567 27 : oid o = 0;
568 27 : InstrPtr p;
569 27 : str oper;
570 :
571 27 : (void) cntxt;
572 27 : p = findGeneratorDefinition(mb,pci,pci->argv[1]);
573 27 : if( p == NULL)
574 0 : throw(MAL,"generator.thetaselect",SQLSTATE(42000) "Could not locate definition for object");
575 :
576 27 : assert(pci->argc == 5); // candidate list included
577 27 : cndid = *getArgReference_bat(stk,pci, 2);
578 27 : if( !is_bat_nil(cndid)){
579 2 : cand = BATdescriptor(cndid);
580 2 : if( cand == NULL)
581 0 : throw(MAL,"generator.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
582 2 : canditer_init(&ci, NULL, cand);
583 : }
584 27 : oper= *getArgReference_str(stk,pci,4);
585 :
586 : // check the step direction
587 :
588 27 : switch( tpe =getArgType(mb,pci,3)){
589 119 : case TYPE_bte: VLTthetasubselect(bte,abs);break;
590 0 : case TYPE_sht: VLTthetasubselect(sht,abs);break;
591 0 : case TYPE_int: VLTthetasubselect(int,abs);break;
592 16 : case TYPE_lng: VLTthetasubselect(lng,llabs);break;
593 : #ifdef HAVE_HGE
594 0 : case TYPE_hge: VLTthetasubselect(hge,HGE_ABS);break;
595 : #endif
596 8 : case TYPE_flt: VLTthetasubselect(flt,fabsf);break;
597 25 : case TYPE_dbl: VLTthetasubselect(dbl,fabs);break;
598 : break;
599 9 : default:
600 9 : if ( tpe == TYPE_timestamp){
601 9 : timestamp f,l, val, low, hgh;
602 9 : lng s;
603 9 : oid *v;
604 :
605 9 : f = *getArgReference_TYPE(stk,p, 1, timestamp);
606 9 : l = *getArgReference_TYPE(stk,p, 2, timestamp);
607 9 : if ( p->argc == 3) {
608 0 : BBPreclaim(cand);
609 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
610 : }
611 9 : s = *getArgReference_lng(stk,p, 3);
612 9 : if ( s == 0 ||
613 9 : (s > 0 && f > l) ||
614 9 : (s < 0 && f < l)
615 : ) {
616 0 : BBPreclaim(cand);
617 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
618 : }
619 :
620 9 : hgh = low = timestamp_nil;
621 9 : if ( strcmp(oper,"<") == 0){
622 5 : hgh= *getArgReference_TYPE(stk,pci,3, timestamp);
623 5 : hgh = timestamp_add_usec(hgh, -1);
624 5 : if (is_timestamp_nil(hgh)) {
625 0 : BBPreclaim(cand);
626 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
627 : }
628 : } else
629 4 : if ( strcmp(oper,"<=") == 0){
630 0 : hgh= *getArgReference_TYPE(stk,pci,3, timestamp) ;
631 : } else
632 4 : if ( strcmp(oper,">") == 0){
633 3 : low= *getArgReference_TYPE(stk,pci,3, timestamp);
634 3 : low = timestamp_add_usec(low, 1);
635 3 : if (is_timestamp_nil(low)) {
636 0 : BBPreclaim(cand);
637 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
638 : }
639 : } else
640 1 : if ( strcmp(oper,">=") == 0){
641 0 : low= *getArgReference_TYPE(stk,pci,3, timestamp);
642 : } else
643 1 : if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
644 0 : hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
645 0 : anti = 1;
646 : } else
647 1 : if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
648 1 : hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
649 : } else {
650 0 : BBPreclaim(cand);
651 0 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
652 : }
653 :
654 9 : s *= 1000; /* msec -> usec */
655 9 : cap = (BUN) (timestamp_diff(l, f) / s);
656 9 : bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
657 9 : if( bn == NULL) {
658 0 : BBPreclaim(cand);
659 0 : throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
660 : }
661 9 : v = (oid*) Tloc(bn,0);
662 :
663 9 : val = f;
664 85 : for(j = 0; j< cap; j++, o++){
665 148 : if (((is_timestamp_nil(low) || val >= low) &&
666 50 : (is_timestamp_nil(hgh) || val <= hgh)) != anti){
667 34 : if(cand == NULL || canditer_contains(&ci, o)){
668 31 : *v++ = o;
669 31 : c++;
670 : }
671 : }
672 76 : val = timestamp_add_usec(val, s);
673 76 : if (is_timestamp_nil(val)) {
674 0 : BBPreclaim(cand);
675 0 : BBPreclaim(bn);
676 0 : throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
677 : }
678 : }
679 : } else {
680 0 : BBPreclaim(cand);
681 0 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal generator arguments");
682 : }
683 : }
684 :
685 27 : if( cndid)
686 27 : BBPunfix(cndid);
687 27 : BATsetcount(bn,c);
688 27 : bn->tsorted = true;
689 27 : bn->trevsorted = false;
690 27 : bn->tkey = true;
691 27 : bn->tnil = false;
692 27 : bn->tnonil = true;
693 27 : *getArgReference_bat(stk,pci,0) = bn->batCacheid;
694 27 : BBPkeepref(bn);
695 27 : return MAL_SUCCEED;
696 : }
697 :
698 : #define VLTprojection(TPE) \
699 : do { \
700 : TPE f,l,s, val; \
701 : TPE *v; \
702 : f = *getArgReference_##TPE(stk,p, 1); \
703 : l = *getArgReference_##TPE(stk,p, 2); \
704 : if ( p->argc == 3) \
705 : s = f<l? (TPE) 1: (TPE)-1; \
706 : else \
707 : s = * getArgReference_##TPE(stk, p, 3); \
708 : if ( s == 0 || (f> l && s>0) || (f<l && s < 0)) { \
709 : BBPunfix(b->batCacheid); \
710 : throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range"); \
711 : } \
712 : bn = COLnew(0, TYPE_##TPE, cnt, TRANSIENT); \
713 : if( bn == NULL){ \
714 : BBPunfix(b->batCacheid); \
715 : throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
716 : } \
717 : v = (TPE*) Tloc(bn,0); \
718 : for(; cnt-- > 0; o++){ \
719 : val = f + ((TPE) (ol == NULL ? o : ol[o])) * s; \
720 : if ( (s > 0 && (val < f || val >= l)) || (s < 0 && (val <= l || val > f))) \
721 : continue; \
722 : *v++ = val; \
723 : c++; \
724 : } \
725 : } while (0)
726 :
727 130 : str VLTgenerator_projection(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
728 : {
729 130 : int tpe;
730 130 : bat *ret;
731 130 : BAT *b, *bn = NULL;
732 130 : BUN cnt, c = 0;
733 130 : oid *ol = NULL, o= 0;
734 130 : InstrPtr p;
735 :
736 130 : (void) cntxt;
737 130 : p = findGeneratorDefinition(mb,pci,pci->argv[2]);
738 :
739 130 : ret = getArgReference_bat(stk,pci,0);
740 130 : b = BATdescriptor(*getArgReference_bat(stk,pci,1));
741 130 : if( b == NULL)
742 0 : throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
743 :
744 : // if it does not exist we should fall back to the ordinary projection to try
745 : // it might have been materialized already
746 130 : if( p == NULL){
747 0 : bn = BATdescriptor( *getArgReference_bat(stk,pci,2));
748 0 : if( bn == NULL) {
749 0 : BBPunfix(b->batCacheid);
750 0 : throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
751 : }
752 0 : BAT *bp = BATproject(b, bn);
753 0 : BBPunfix(b->batCacheid);
754 0 : BBPunfix(bn->batCacheid);
755 0 : if (bp == NULL)
756 0 : throw(MAL, "generator.projection", GDK_EXCEPTION);
757 0 : *ret = bp->batCacheid;
758 0 : BBPkeepref(bp);
759 0 : return MAL_SUCCEED;
760 : }
761 :
762 130 : cnt = BATcount(b);
763 130 : if ( b->ttype == TYPE_void)
764 50 : o = b->tseqbase;
765 : else
766 80 : ol = (oid*) Tloc(b,0);
767 :
768 : /* the actual code to perform a projection over generators */
769 130 : switch( tpe = getArgType(mb,p,1)){
770 431 : case TYPE_bte: VLTprojection(bte); break;
771 999008 : case TYPE_sht: VLTprojection(sht); break;
772 1049784 : case TYPE_int: VLTprojection(int); break;
773 14 : case TYPE_lng: VLTprojection(lng); break;
774 : #ifdef HAVE_HGE
775 0 : case TYPE_hge: VLTprojection(hge); break;
776 : #endif
777 7 : case TYPE_flt: VLTprojection(flt); break;
778 17 : case TYPE_dbl: VLTprojection(dbl); break;
779 35 : default:
780 35 : if ( tpe == TYPE_timestamp){
781 35 : timestamp f,l, val;
782 35 : lng s,t;
783 35 : timestamp *v;
784 35 : f = *getArgReference_TYPE(stk,p, 1, timestamp);
785 35 : l = *getArgReference_TYPE(stk,p, 2, timestamp);
786 35 : if ( p->argc == 3) {
787 0 : BBPunfix(b->batCacheid);
788 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
789 : }
790 35 : s = *getArgReference_lng(stk,p, 3);
791 35 : if ( s == 0 ||
792 35 : (s< 0 && f < l) ||
793 35 : (s> 0 && l < f) ) {
794 0 : BBPunfix(b->batCacheid);
795 0 : throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
796 : }
797 :
798 35 : s *= 1000; /* msec -> usec */
799 35 : bn = COLnew(0, TYPE_timestamp, cnt, TRANSIENT);
800 35 : if( bn == NULL){
801 0 : BBPunfix(b->batCacheid);
802 0 : throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
803 : }
804 :
805 35 : v = (timestamp*) Tloc(bn,0);
806 :
807 89 : for(; cnt-- > 0; o++){
808 54 : t = ((lng) (ol == NULL ? o : ol[o])) * s;
809 54 : val = timestamp_add_usec(f, t);
810 54 : if (is_timestamp_nil(val)) {
811 0 : BBPunfix(b->batCacheid);
812 0 : BBPreclaim(bn);
813 0 : throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
814 : }
815 :
816 54 : if ( is_timestamp_nil(val))
817 : continue;
818 54 : if (s > 0 && (val < f || val >= l) )
819 0 : continue;
820 54 : if (s < 0 && (val <= l || val > f) )
821 0 : continue;
822 54 : *v++ = val;
823 54 : c++;
824 : }
825 : }
826 : }
827 :
828 : /* adminstrative wrapup of the projection */
829 130 : BBPunfix(b->batCacheid);
830 130 : if( bn){
831 130 : BATsetcount(bn,c);
832 130 : bn->tsorted = bn->trevsorted = false;
833 130 : bn->tkey = false;
834 130 : bn->tnil = false;
835 130 : bn->tnonil = false;
836 130 : *getArgReference_bat(stk,pci,0) = bn->batCacheid;
837 130 : BBPkeepref(bn);
838 : }
839 : return MAL_SUCCEED;
840 : }
841 :
842 : /* The operands of a join operation can either be defined on a generator */
843 : #define VLTjoin(TPE, ABS) \
844 : do { \
845 : TPE f,l,s; TPE *v; BUN w; \
846 : f = *getArgReference_##TPE(stk,p, 1); \
847 : l = *getArgReference_##TPE(stk,p, 2); \
848 : if ( p->argc == 3) \
849 : s = f<l? (TPE) 1: (TPE)-1; \
850 : else \
851 : s = * getArgReference_##TPE(stk, p, 3); \
852 : incr = s > 0; \
853 : v = (TPE*) Tloc(b,0); \
854 : if ( s == 0 || (f> l && s>0) || (f<l && s < 0)) { \
855 : BBPunfix(bln->batCacheid); \
856 : BBPunfix(brn->batCacheid); \
857 : BBPreclaim(bl); \
858 : BBPreclaim(br); \
859 : throw(MAL,"generator.join", SQLSTATE(42000) "Illegal range"); \
860 : } \
861 : for( ; cnt >0; cnt--,o++,v++){ \
862 : w = (BUN) (ABS(*v -f)/ABS(s)); \
863 : if ( f + (TPE)(w * s) == *v ){ \
864 : *ol++ = (oid) w; \
865 : *or++ = o; \
866 : c++; \
867 : } \
868 : } \
869 : } while (0)
870 :
871 0 : str VLTgenerator_join(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
872 : {
873 0 : BAT *b, *bl = NULL, *br = NULL, *bln = NULL, *brn= NULL;
874 0 : BUN cnt,c =0;
875 0 : oid o= 0, *ol, *or;
876 0 : int tpe, incr=0, materialized = 0;
877 0 : InstrPtr p = NULL, q = NULL;
878 0 : str msg = MAL_SUCCEED;
879 :
880 0 : (void) cntxt;
881 : // we assume at most one of the arguments to refer to the generator
882 0 : p = findGeneratorDefinition(mb,pci,pci->argv[2]);
883 0 : q = findGeneratorDefinition(mb,pci,pci->argv[3]);
884 :
885 0 : if (p == NULL && q == NULL) {
886 0 : bl = BATdescriptor(*getArgReference_bat(stk, pci, 2));
887 0 : br = BATdescriptor(*getArgReference_bat(stk, pci, 3));
888 0 : if (bl == NULL || br == NULL) {
889 0 : BBPreclaim(bl);
890 0 : BBPreclaim(br);
891 0 : throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
892 : }
893 0 : gdk_return rc = BATjoin(&bln, &brn, bl, br, NULL, NULL, false, BUN_NONE);
894 0 : BBPunfix(bl->batCacheid);
895 0 : BBPunfix(br->batCacheid);
896 0 : if (rc != GDK_SUCCEED)
897 0 : throw(MAL,"generator.join", GDK_EXCEPTION);
898 0 : *getArgReference_bat(stk, pci, 0) = bln->batCacheid;
899 0 : *getArgReference_bat(stk, pci, 1) = brn->batCacheid;
900 0 : BBPkeepref(bln);
901 0 : BBPkeepref(brn);
902 0 : return MAL_SUCCEED;
903 : }
904 :
905 0 : if( p == NULL){
906 0 : bl = BATdescriptor(*getArgReference_bat(stk,pci,2));
907 0 : if( bl == NULL)
908 0 : throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
909 : }
910 0 : if ( q == NULL){
911 : /* p != NULL, hence bl == NULL */
912 0 : br = BATdescriptor(*getArgReference_bat(stk,pci,3));
913 0 : if( br == NULL)
914 0 : throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
915 : }
916 :
917 : // in case of both generators || getModuleId(q) == generatorRef)materialize the 'smallest' one first
918 : // or implement more knowledge, postponed
919 0 : if (p && q ){
920 0 : msg = VLTgenerator_table_(&bl, cntxt, mb, stk, p);
921 0 : if( msg || bl == NULL )
922 0 : throw(MAL,"generator.join",SQLSTATE(42000) "Join over generator pairs not supported");
923 : else
924 : p = NULL;
925 : materialized =1;
926 : }
927 :
928 : // switch roles to have a single target bat[:oid,:any] designated
929 : // by b and reference instruction p for the generator
930 0 : b = q? bl : br;
931 0 : p = q? q : p;
932 0 : cnt = BATcount(b);
933 0 : tpe = b->ttype;
934 0 : o= b->hseqbase;
935 :
936 0 : bln = COLnew(0,TYPE_oid, cnt, TRANSIENT);
937 0 : brn = COLnew(0,TYPE_oid, cnt, TRANSIENT);
938 0 : if( bln == NULL || brn == NULL){
939 0 : BBPreclaim(bln);
940 0 : BBPreclaim(brn);
941 0 : BBPreclaim(bl);
942 0 : BBPreclaim(br);
943 0 : throw(MAL,"generator.join", SQLSTATE(HY013) MAL_MALLOC_FAIL);
944 : }
945 0 : ol = (oid*) Tloc(bln,0);
946 0 : or = (oid*) Tloc(brn,0);
947 :
948 : /* The actual join code for generators be injected here */
949 0 : switch(tpe){
950 0 : case TYPE_bte: VLTjoin(bte,abs); break;
951 0 : case TYPE_sht: VLTjoin(sht,abs); break;
952 0 : case TYPE_int: VLTjoin(int,abs); break;
953 0 : case TYPE_lng: VLTjoin(lng,llabs); break;
954 : #ifdef HAVE_HGE
955 0 : case TYPE_hge: VLTjoin(hge,HGE_ABS); break;
956 : #endif
957 0 : case TYPE_flt: VLTjoin(flt,fabsf); break;
958 0 : case TYPE_dbl: VLTjoin(dbl,fabs); break;
959 : default:
960 0 : if( tpe == TYPE_timestamp){
961 : // it is easier to produce the timestamp series
962 : // then to estimate the possible index
963 0 : }
964 0 : BBPunfix(bln->batCacheid);
965 0 : BBPunfix(brn->batCacheid);
966 0 : BBPreclaim(bl);
967 0 : BBPreclaim(br);
968 0 : throw(MAL,"generator.join", SQLSTATE(42000) "Illegal type");
969 : }
970 :
971 0 : BATsetcount(bln,c);
972 0 : bln->tsorted = bln->trevsorted = false;
973 0 : bln->tkey = false;
974 0 : bln->tnil = false;
975 0 : bln->tnonil = false;
976 0 : bln->tsorted = incr || c <= 1;
977 0 : bln->trevsorted = !incr || c <= 1;
978 :
979 0 : BATsetcount(brn,c);
980 0 : brn->tsorted = brn->trevsorted = false;
981 0 : brn->tkey = false;
982 0 : brn->tnil = false;
983 0 : brn->tnonil = false;
984 0 : brn->tsorted = incr || c <= 1;
985 0 : brn->trevsorted = !incr || c <= 1;
986 0 : if( q){
987 0 : *getArgReference_bat(stk,pci,0) = brn->batCacheid;
988 0 : BBPkeepref(brn);
989 0 : *getArgReference_bat(stk,pci,1) = bln->batCacheid;
990 0 : BBPkeepref(bln);
991 : } else {
992 0 : *getArgReference_bat(stk,pci,0) = bln->batCacheid;
993 0 : BBPkeepref(bln);
994 0 : *getArgReference_bat(stk,pci,1) = brn->batCacheid;
995 0 : BBPkeepref(brn);
996 : }
997 0 : if ( materialized){
998 0 : BBPreclaim(bl);
999 0 : bl = 0;
1000 : }
1001 0 : BBPreclaim(bl);
1002 0 : BBPreclaim(br);
1003 : return msg;
1004 : }
1005 :
1006 : #define VLTrangeExpand() \
1007 : do { \
1008 : limit+= cnt * (limit/(done?done:1)+1); \
1009 : if (BATextend(bln, limit) != GDK_SUCCEED) { \
1010 : BBPunfix(blow->batCacheid); \
1011 : BBPunfix(bhgh->batCacheid); \
1012 : BBPunfix(bln->batCacheid); \
1013 : BBPunfix(brn->batCacheid); \
1014 : throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
1015 : } \
1016 : if (BATextend(brn, limit) != GDK_SUCCEED) { \
1017 : BBPunfix(blow->batCacheid); \
1018 : BBPunfix(bhgh->batCacheid); \
1019 : BBPunfix(bln->batCacheid); \
1020 : BBPunfix(brn->batCacheid); \
1021 : throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
1022 : } \
1023 : ol = (oid*) Tloc(bln,0) + c; \
1024 : or = (oid*) Tloc(brn,0) + c; \
1025 : } while (0)
1026 :
1027 : /* The operands of a join operation can either be defined on a generator */
1028 : #define VLTrangejoin(TPE, ABS, FLOOR) \
1029 : do { \
1030 : TPE f,f1,l,s; TPE *vlow,*vhgh; BUN w; \
1031 : f = *getArgReference_##TPE(stk,p, 1); \
1032 : l = *getArgReference_##TPE(stk,p, 2); \
1033 : if ( p->argc == 3) \
1034 : s = f<l? (TPE) 1: (TPE)-1; \
1035 : else \
1036 : s = * getArgReference_##TPE(stk, p, 3); \
1037 : incr = s > 0; \
1038 : if ( s == 0 || (f> l && s>0) || (f<l && s < 0)) { \
1039 : BBPreclaim(bln); \
1040 : BBPreclaim(brn); \
1041 : BBPreclaim(blow); \
1042 : BBPreclaim(bhgh); \
1043 : throw(MAL,"generator.rangejoin", SQLSTATE(42000) "Illegal range"); \
1044 : } \
1045 : vlow = (TPE*) Tloc(blow,0); \
1046 : vhgh = (TPE*) Tloc(bhgh,0); \
1047 : for( ; cnt >0; cnt--, done++, o++,vlow++,vhgh++){ \
1048 : f1 = f + FLOOR(ABS(*vlow-f)/ABS(s)) * s; \
1049 : if ( f1 < *vlow ) \
1050 : f1+= s; \
1051 : w = (BUN) FLOOR(ABS(f1-f)/ABS(s)); \
1052 : for( ; (f1 > *vlow || (li && f1 == *vlow)) && (f1 < *vhgh || (ri && f1 == *vhgh)); f1 += s, w++){ \
1053 : if(c == limit) \
1054 : VLTrangeExpand(); \
1055 : *ol++ = (oid) w; \
1056 : *or++ = o; \
1057 : c++; \
1058 : } \
1059 : } \
1060 : } while (0)
1061 :
1062 0 : str VLTgenerator_rangejoin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1063 : {
1064 0 : BAT *blow = NULL, *bhgh = NULL, *bln = NULL, *brn= NULL;
1065 0 : bit li,ri;
1066 0 : BUN limit, cnt, done=0, c =0;
1067 0 : oid o= 0, *ol, *or;
1068 0 : int tpe, incr=0;
1069 0 : InstrPtr p = NULL;
1070 0 : str msg = MAL_SUCCEED;
1071 :
1072 0 : (void) cntxt;
1073 : // the left join argument should be a generator
1074 0 : p = findGeneratorDefinition(mb,pci,pci->argv[2]);
1075 0 : if( p == NULL)
1076 0 : throw(MAL,"generator.rangejoin",SQLSTATE(42000) "Invalid arguments");
1077 :
1078 0 : blow = BATdescriptor(*getArgReference_bat(stk,pci,3));
1079 0 : if( blow == NULL)
1080 0 : throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1081 :
1082 0 : bhgh = BATdescriptor(*getArgReference_bat(stk,pci,4));
1083 0 : if( bhgh == NULL){
1084 0 : BBPunfix(blow->batCacheid);
1085 0 : throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1086 : }
1087 0 : li = *getArgReference_bit(stk,pci,5);
1088 0 : ri = *getArgReference_bit(stk,pci,6);
1089 :
1090 0 : cnt = BATcount(blow);
1091 0 : limit = 2 * cnt; //top off result before expansion
1092 0 : tpe = blow->ttype;
1093 0 : o= blow->hseqbase;
1094 :
1095 0 : bln = COLnew(0,TYPE_oid, limit, TRANSIENT);
1096 0 : brn = COLnew(0,TYPE_oid, limit, TRANSIENT);
1097 0 : if( bln == NULL || brn == NULL){
1098 0 : BBPreclaim(bln);
1099 0 : BBPreclaim(brn);
1100 0 : BBPreclaim(blow);
1101 0 : BBPreclaim(bhgh);
1102 0 : throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1103 : }
1104 0 : ol = (oid*) Tloc(bln,0);
1105 0 : or = (oid*) Tloc(brn,0);
1106 :
1107 : /* The actual join code for generators be injected here */
1108 0 : switch(tpe){
1109 0 : case TYPE_bte: VLTrangejoin(bte,abs,IDENTITY); break;
1110 0 : case TYPE_sht: VLTrangejoin(sht,abs,IDENTITY); break;
1111 0 : case TYPE_int: VLTrangejoin(int,abs,IDENTITY); break;
1112 0 : case TYPE_lng: VLTrangejoin(lng,llabs,IDENTITY); break;
1113 : #ifdef HAVE_HGE
1114 0 : case TYPE_hge: VLTrangejoin(hge,HGE_ABS,IDENTITY); break;
1115 : #endif
1116 0 : case TYPE_flt: VLTrangejoin(flt,fabsf,floorf); break;
1117 0 : case TYPE_dbl: VLTrangejoin(dbl,fabs,floor); break;
1118 : default:
1119 0 : if( tpe == TYPE_timestamp){
1120 : // it is easier to produce the timestamp series
1121 : // then to estimate the possible index
1122 0 : }
1123 0 : BBPreclaim(bln);
1124 0 : BBPreclaim(brn);
1125 0 : BBPreclaim(blow);
1126 0 : BBPreclaim(bhgh);
1127 0 : throw(MAL,"generator.rangejoin","Illegal type");
1128 : }
1129 :
1130 0 : BATsetcount(bln,c);
1131 0 : bln->tsorted = bln->trevsorted = false;
1132 0 : bln->tkey = false;
1133 0 : bln->tnil = false;
1134 0 : bln->tnonil = false;
1135 0 : bln->tsorted = incr || c <= 1;
1136 0 : bln->trevsorted = !incr || c <= 1;
1137 :
1138 0 : BATsetcount(brn,c);
1139 0 : brn->tsorted = brn->trevsorted = false;
1140 0 : brn->tkey = false;
1141 0 : brn->tnil = false;
1142 0 : brn->tnonil = false;
1143 0 : brn->tsorted = incr || c <= 1;
1144 0 : brn->trevsorted = !incr || c <= 1;
1145 0 : *getArgReference_bat(stk,pci,0) = bln->batCacheid;
1146 0 : BBPkeepref(bln);
1147 0 : *getArgReference_bat(stk,pci,1) = brn->batCacheid;
1148 0 : BBPkeepref(brn);
1149 0 : BBPreclaim(blow);
1150 0 : BBPreclaim(bhgh);
1151 0 : return msg;
1152 : }
1153 :
1154 : #include "mel.h"
1155 : static mel_func generator_init_funcs[] = {
1156 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
1157 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
1158 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
1159 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
1160 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
1161 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
1162 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
1163 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
1164 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
1165 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
1166 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
1167 : pattern("generator", "series", VLTgenerator_table, false, "Create and materialize a generator table", args(1,4, batarg("",dbl),arg("first",dbl),arg("limit",dbl),arg("step",dbl))),
1168 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",timestamp),arg("first",timestamp),arg("limit",timestamp),arg("step",lng))),
1169 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
1170 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
1171 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
1172 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
1173 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
1174 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",dbl),arg("first",dbl),arg("limit",dbl),arg("step",dbl))),
1175 : pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize", args(1,4, batarg("",timestamp),arg("first",timestamp),arg("limit",timestamp),arg("step",lng))),
1176 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
1177 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
1178 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
1179 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
1180 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
1181 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
1182 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",bte),batarg("cnd",oid),arg("low",bte),arg("oper",str))),
1183 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",sht),batarg("cnd",oid),arg("low",sht),arg("oper",str))),
1184 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",int),batarg("cnd",oid),arg("low",int),arg("oper",str))),
1185 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",lng),batarg("cnd",oid),arg("low",lng),arg("oper",str))),
1186 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",flt),batarg("cnd",oid),arg("low",flt),arg("oper",str))),
1187 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",dbl),batarg("cnd",oid),arg("low",dbl),arg("oper",str))),
1188 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "Overloaded selection routine", args(1,5, batarg("",oid),batarg("b",timestamp),batarg("cnd",oid),arg("low",timestamp),arg("oper",str))),
1189 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",bte),arg("low",bte),arg("high",bte),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1190 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",sht),arg("low",sht),arg("high",sht),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1191 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",int),arg("low",int),arg("high",int),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1192 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",lng),arg("low",lng),arg("high",lng),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1193 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",flt),arg("low",flt),arg("high",flt),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1194 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",dbl),arg("low",dbl),arg("high",dbl),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1195 : pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,7, batarg("",oid),batarg("b",timestamp),arg("low",timestamp),arg("high",timestamp),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1196 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",bte),batarg("cand",oid),arg("low",bte),arg("high",bte),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1197 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",sht),batarg("cand",oid),arg("low",sht),arg("high",sht),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1198 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",int),batarg("cand",oid),arg("low",int),arg("high",int),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1199 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",lng),batarg("cand",oid),arg("low",lng),arg("high",lng),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1200 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",flt),batarg("cand",oid),arg("low",flt),arg("high",flt),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1201 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",dbl),batarg("cand",oid),arg("low",dbl),arg("high",dbl),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1202 : pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,8, batarg("",oid),batarg("b",timestamp),batarg("cand",oid),arg("low",timestamp),arg("high",timestamp),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1203 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",bte),batarg("b",oid),batarg("cand",bte))),
1204 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",sht),batarg("b",oid),batarg("cand",sht))),
1205 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",int),batarg("b",oid),batarg("cand",int))),
1206 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",lng),batarg("b",oid),batarg("cand",lng))),
1207 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",flt),batarg("b",oid),batarg("cand",flt))),
1208 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",dbl),batarg("b",oid),batarg("cand",dbl))),
1209 : pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",timestamp),batarg("b",oid),batarg("cand",timestamp))),
1210 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",bte),batarg("gen",bte))),
1211 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",sht),batarg("gen",sht))),
1212 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",int),batarg("gen",int))),
1213 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",lng),batarg("gen",lng))),
1214 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",flt),batarg("gen",flt))),
1215 : pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",dbl),batarg("gen",dbl))),
1216 : pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",bte),batarg("low",bte),batarg("hgh",bte),arg("li",bit),arg("ri",bit))),
1217 : pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",sht),batarg("low",sht),batarg("hgh",sht),arg("li",bit),arg("ri",bit))),
1218 : pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",int),batarg("low",int),batarg("hgh",int),arg("li",bit),arg("ri",bit))),
1219 : pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",lng),batarg("low",lng),batarg("hgh",lng),arg("li",bit),arg("ri",bit))),
1220 : pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",flt),batarg("low",flt),batarg("hgh",flt),arg("li",bit),arg("ri",bit))),
1221 : pattern("generator", "join", VLTgenerator_rangejoin, false, "Overloaded range join operation", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",dbl),batarg("low",dbl),batarg("hgh",dbl),arg("li",bit),arg("ri",bit))),
1222 : #ifdef HAVE_HGE
1223 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
1224 : pattern("generator", "series", VLTgenerator_table, false, "Create and materialize a generator table", args(1,4, batarg("",hge),arg("first",hge),arg("limit",hge),arg("step",hge))),
1225 : pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize", args(1,4, batarg("",hge),arg("first",hge),arg("limit",hge),arg("step",hge))),
1226 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
1227 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "Overloaded selection routine", args(1,5, batarg("",oid),batarg("b",hge),batarg("cnd",oid),arg("low",hge),arg("oper",str))),
1228 : pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,7, batarg("",oid),batarg("b",hge),arg("low",hge),arg("high",hge),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1229 : pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,8, batarg("",oid),batarg("b",hge),batarg("cand",oid),arg("low",hge),arg("high",hge),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1230 : pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",hge),batarg("b",oid),batarg("cand",hge))),
1231 : pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",hge),batarg("gen",hge))),
1232 : #endif
1233 : { .imp=NULL }
1234 : };
1235 : #include "mal_import.h"
1236 : #ifdef _MSC_VER
1237 : #undef read
1238 : #pragma section(".CRT$XCU",read)
1239 : #endif
1240 324 : LIB_STARTUP_FUNC(init_generator_mal)
1241 324 : { mal_module("generator", NULL, generator_init_funcs); }
|