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, date 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 254 : VLTgenerator_noop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
39 : {
40 254 : int nullerr= 0, zeroerror=0, tpe;
41 254 : (void) cntxt;
42 :
43 254 : switch( tpe = getArgType(mb,pci,1)){
44 117 : case TYPE_bte: VLTnoop(bte); break;
45 26 : case TYPE_sht: VLTnoop(sht); break;
46 36 : case TYPE_int: VLTnoop(int); break;
47 17 : case TYPE_lng: VLTnoop(lng); break;
48 : #ifdef HAVE_HGE
49 9 : case TYPE_hge: VLTnoop(hge); break;
50 : #endif
51 6 : case TYPE_flt: VLTnoop(flt); break;
52 10 : case TYPE_dbl: VLTnoop(dbl); break;
53 33 : default:
54 33 : if (tpe == TYPE_date) {
55 : /* with date, step is of SQL type "interval month or day",
56 : * i.e., MAL / C type "int" or "lng" */
57 4 : int steptpe = pci->argc==4 ? getArgType(mb,pci,3) : 0;
58 4 : if (steptpe == TYPE_int)
59 2 : VLTnoop(int);
60 : else /* default interval days */
61 2 : VLTnoop(lng);
62 29 : } else if (tpe == TYPE_timestamp) {
63 : /* with timestamp, step is of SQL type "interval seconds",
64 : * i.e., MAL / C type "lng" */
65 29 : VLTnoop(lng);
66 : } else {
67 0 : throw(MAL,"generator.noop", SQLSTATE(42000) "unknown data type %d", getArgType(mb,pci,1));
68 : }
69 : }
70 254 : if( zeroerror)
71 2 : throw(MAL,"generator.noop", SQLSTATE(42000) "Zero step size not allowed");
72 252 : if( nullerr)
73 2 : throw(MAL,"generator.noop", SQLSTATE(42000) "Null step size not allowed");
74 : return MAL_SUCCEED;
75 : }
76 :
77 : #define check_bte() ((void)0)
78 : #define check_sht() ((void)0)
79 : #if SIZEOF_BUN < SIZEOF_LNG
80 : #define check_int() \
81 : do { \
82 : if (cnt > (unsigned int) BUN_MAX) \
83 : throw(MAL, "generator.table", \
84 : SQLSTATE(42000) "Illegal generator range"); \
85 : } while (0)
86 : #else
87 : #define check_int() ((void)0)
88 : #endif
89 : #define check_lng() \
90 : do { \
91 : if (cnt > (ulng) BUN_MAX) \
92 : throw(MAL, "generator.table", \
93 : SQLSTATE(42000) "Illegal generator range"); \
94 : } while (0)
95 : #ifdef HAVE_HGE
96 : #define check_hge() \
97 : do { \
98 : if (cnt > (uhge) BUN_MAX) \
99 : throw(MAL, "generator.table", \
100 : SQLSTATE(42000) "Illegal generator range"); \
101 : } while (0)
102 : #endif
103 :
104 : #define VLTmaterialize(TPE, uTPE) \
105 : do { \
106 : TPE f, l, s; \
107 : uTPE cnt; \
108 : \
109 : f = *getArgReference_##TPE(stk, pci, 1); \
110 : l = *getArgReference_##TPE(stk, pci, 2); \
111 : if ( pci->argc == 3) \
112 : s = f <= l ? (TPE) 1 : (TPE) -1; \
113 : else \
114 : s = *getArgReference_##TPE(stk,pci, 3); \
115 : if (s == 0 || is_##TPE##_nil(f) || is_##TPE##_nil(l) || is_##TPE##_nil(s)) \
116 : throw(MAL, "generator.table", \
117 : SQLSTATE(42000) "Illegal generator range"); \
118 : if (f == l) { \
119 : cnt = 0; \
120 : } else if (f < l) { \
121 : /* cnt = l - f */ \
122 : if (s <= 0) \
123 : throw(MAL, "generator.table", \
124 : SQLSTATE(42000) "Illegal generator range"); \
125 : if (f >= 0 || l <= 0) { \
126 : /* no chance of any kind of overflow */ \
127 : cnt = l - f; \
128 : } else { \
129 : /* f < 0 && l > 0, do calculation is unsigned type */ \
130 : cnt = (uTPE) l + (uTPE) -f; \
131 : } \
132 : uTPE i = cnt / (uTPE) s; \
133 : if (i * (uTPE) s != cnt) \
134 : i++; \
135 : cnt = i; \
136 : } else { \
137 : /* l < f; cnt = f - l */ \
138 : if (s >= 0) \
139 : throw(MAL, "generator.table", \
140 : SQLSTATE(42000) "Illegal generator range"); \
141 : if (l >= 0 || f <= 0) { \
142 : /* no chance of any kind of overflow */ \
143 : cnt = f - l; \
144 : } else { \
145 : /* f > 0 && l < 0, do calculation is unsigned type */ \
146 : cnt = (uTPE) f + (uTPE) -l; \
147 : } \
148 : uTPE i = cnt / (uTPE) -s; \
149 : if (i * (uTPE) -s != cnt) \
150 : i++; \
151 : cnt = i; \
152 : } \
153 : check_##TPE(); \
154 : n = (BUN) cnt; \
155 : bn = COLnew(0, TYPE_##TPE, n, TRANSIENT); \
156 : if (bn == NULL) \
157 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
158 : TPE *v = (TPE *) Tloc(bn, 0); \
159 : while (cnt > 0) { \
160 : *v++ = f; \
161 : f += s; \
162 : cnt--; \
163 : } \
164 : bn->tsorted = s > 0 || n <= 1; \
165 : bn->trevsorted = s < 0 || n <= 1; \
166 : } while (0)
167 :
168 : #define VLTmaterialize_flt(TPE) \
169 : do { \
170 : TPE *v, f, l, s; \
171 : f = *getArgReference_##TPE(stk, pci, 1); \
172 : l = *getArgReference_##TPE(stk, pci, 2); \
173 : if ( pci->argc == 3) \
174 : s = f<l? (TPE) 1: (TPE)-1; \
175 : else s = *getArgReference_##TPE(stk,pci, 3); \
176 : if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) \
177 : throw(MAL, "generator.table", \
178 : SQLSTATE(42000) "Illegal generator range"); \
179 : n = (BUN) ((l - f) / s); \
180 : if ((TPE) (n * s + f) != l) \
181 : n++; \
182 : bn = COLnew(0, TYPE_##TPE, n, TRANSIENT); \
183 : if (bn == NULL) \
184 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
185 : v = (TPE*) Tloc(bn, 0); \
186 : for (BUN c = 0; c < n; c++) \
187 : *v++ = (TPE) (f + c * s); \
188 : bn->tsorted = s > 0 || n <= 1; \
189 : bn->trevsorted = s < 0 || n <= 1; \
190 : } while (0)
191 :
192 : static str
193 223 : VLTgenerator_table_(BAT **result, Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
194 : {
195 223 : BAT *bn;
196 223 : int tpe;
197 223 : (void) cntxt;
198 223 : BUN n;
199 :
200 223 : *result = NULL;
201 223 : tpe = getArgType(mb, pci, 1);
202 223 : switch (tpe) {
203 102 : case TYPE_bte:
204 1848 : VLTmaterialize(bte, uint8_t);
205 87 : break;
206 26 : case TYPE_sht:
207 68020 : VLTmaterialize(sht, uint16_t);
208 23 : break;
209 36 : case TYPE_int:
210 118986496 : VLTmaterialize(int, unsigned);
211 33 : break;
212 15 : case TYPE_lng:
213 60 : VLTmaterialize(lng, ulng);
214 11 : break;
215 : #ifdef HAVE_HGE
216 9 : case TYPE_hge:
217 1384 : VLTmaterialize(hge, uhge);
218 9 : break;
219 : #endif
220 5 : case TYPE_flt:
221 28 : VLTmaterialize_flt(flt);
222 5 : break;
223 8 : case TYPE_dbl:
224 53 : VLTmaterialize_flt(dbl);
225 8 : break;
226 22 : default:
227 22 : if (tpe == TYPE_date && pci->argc == 3)
228 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Date step missing");
229 2 : if (tpe == TYPE_date && getArgType(mb, pci, 3) == TYPE_int) { /* months */
230 1 : date *v,f,l;
231 1 : int s;
232 1 : ValRecord ret;
233 1 : if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
234 1 : &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
235 0 : throw(MAL, "generator.table",
236 : SQLSTATE(42000) "Illegal generator expression range");
237 1 : f = *getArgReference_TYPE(stk, pci, 1, date);
238 1 : l = *getArgReference_TYPE(stk, pci, 2, date);
239 1 : s = *getArgReference_int(stk, pci, 3);
240 1 : if (s == 0 ||
241 1 : (s > 0 && ret.val.btval > 0) ||
242 0 : (s < 0 && ret.val.btval < 0) ||
243 1 : is_date_nil(f) || is_date_nil(l))
244 0 : throw(MAL, "generator.table",
245 : SQLSTATE(42000) "Illegal generator range");
246 1 : n = (BUN) (date_diff(l, f) / (s *28)); /* n maybe too large now */
247 1 : bn = COLnew(0, TYPE_date, n + 1, TRANSIENT);
248 1 : if (bn == NULL)
249 0 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
250 1 : v = (date *) Tloc(bn, 0);
251 1 : BUN c;
252 4 : for (c = 0; c < n && f < l; c++) {
253 3 : *v++ = f;
254 3 : f = date_add_month(f, s);
255 3 : if (is_date_nil(f)) {
256 0 : BBPreclaim(bn);
257 0 : throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
258 : }
259 : }
260 1 : n = c;
261 1 : bn->tsorted = s > 0 || n <= 1;
262 1 : bn->trevsorted = s < 0 || n <= 1;
263 1 : } else if (tpe == TYPE_date) { /* days */
264 1 : date *v,f,l;
265 1 : lng s;
266 1 : ValRecord ret;
267 1 : if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
268 1 : &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
269 0 : throw(MAL, "generator.table",
270 : SQLSTATE(42000) "Illegal generator expression range");
271 1 : f = *getArgReference_TYPE(stk, pci, 1, date);
272 1 : l = *getArgReference_TYPE(stk, pci, 2, date);
273 1 : s = *getArgReference_lng(stk, pci, 3);
274 1 : if (s == 0 ||
275 1 : (s > 0 && ret.val.btval > 0) ||
276 0 : (s < 0 && ret.val.btval < 0) ||
277 1 : is_date_nil(f) || is_date_nil(l))
278 0 : throw(MAL, "generator.table",
279 : SQLSTATE(42000) "Illegal generator range");
280 1 : s /= 24*60*60*1000;
281 : /* check if s is really in nr of days or usecs */
282 1 : n = (BUN) (date_diff(l, f) / s) + 1; /* n maybe too large now */
283 1 : bn = COLnew(0, TYPE_date, n + 1, TRANSIENT);
284 1 : if (bn == NULL)
285 0 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
286 1 : v = (date *) Tloc(bn, 0);
287 1 : BUN c;
288 3 : for (c = 0; c < n && f < l; c++) {
289 2 : *v++ = f;
290 2 : f = date_add_day(f, (int) s);
291 2 : if (is_date_nil(f)) {
292 0 : BBPreclaim(bn);
293 0 : throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
294 : }
295 : }
296 1 : n = c;
297 1 : bn->tsorted = s > 0 || n <= 1;
298 1 : bn->trevsorted = s < 0 || n <= 1;
299 20 : } else if (tpe == TYPE_timestamp) {
300 20 : timestamp *v,f,l;
301 20 : lng s;
302 20 : ValRecord ret;
303 20 : if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
304 20 : &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
305 0 : throw(MAL, "generator.table",
306 : SQLSTATE(42000) "Illegal generator expression range");
307 20 : f = *getArgReference_TYPE(stk, pci, 1, timestamp);
308 20 : l = *getArgReference_TYPE(stk, pci, 2, timestamp);
309 20 : if ( pci->argc == 3)
310 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
311 20 : s = *getArgReference_lng(stk, pci, 3);
312 20 : if (s == 0 ||
313 20 : (s > 0 && ret.val.btval > 0) ||
314 10 : (s < 0 && ret.val.btval < 0) ||
315 20 : is_timestamp_nil(f) || is_timestamp_nil(l))
316 0 : throw(MAL, "generator.table",
317 : SQLSTATE(42000) "Illegal generator range");
318 : /* casting one value to lng causes the whole
319 : * computation to be done as lng, reducing the
320 : * risk of overflow */
321 20 : s *= 1000; /* msec -> usec */
322 20 : n = (BUN) (timestamp_diff(l, f) / s);
323 20 : bn = COLnew(0, TYPE_timestamp, n + 1, TRANSIENT);
324 20 : if (bn == NULL)
325 0 : throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
326 20 : v = (timestamp *) Tloc(bn, 0);
327 166 : for (BUN c = 0; c < n; c++) {
328 146 : *v++ = f;
329 146 : f = timestamp_add_usec(f, s);
330 146 : if (is_timestamp_nil(f)) {
331 0 : BBPreclaim(bn);
332 0 : throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
333 : }
334 : }
335 20 : if (f != l) {
336 11 : *v++ = f;
337 11 : n++;
338 : }
339 20 : bn->tsorted = s > 0 || n <= 1;
340 20 : bn->trevsorted = s < 0 || n <= 1;
341 : } else {
342 0 : throw(MAL, "generator.table", SQLSTATE(42000) "Unsupported type");
343 : }
344 : break;
345 : }
346 198 : BATsetcount(bn, n);
347 198 : bn->tkey = true;
348 198 : bn->tnil = false;
349 198 : bn->tnonil = true;
350 198 : *result = bn;
351 198 : return MAL_SUCCEED;
352 : }
353 :
354 : str
355 227 : VLTgenerator_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
356 : {
357 227 : str msg;
358 227 : BAT *bn = NULL;
359 :
360 227 : if ((msg = VLTgenerator_noop(cntxt, mb, stk, pci)) != MAL_SUCCEED)
361 : return msg;
362 :
363 223 : msg = VLTgenerator_table_(&bn, cntxt, mb, stk, pci);
364 223 : if( msg == MAL_SUCCEED){
365 198 : *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
366 198 : BBPkeepref(bn);
367 : }
368 : return msg;
369 : }
370 :
371 : /*
372 : * Selection over the generator table does not require a materialization of the table
373 : * An optimizer can replace the subselect directly into a generator specific one.
374 : * The target to look for is generator.series(A1,A2,A3)
375 : * We need the generator parameters, which are injected to replace the target column
376 : */
377 : static InstrPtr
378 165 : findGeneratorDefinition(MalBlkPtr mb, InstrPtr pci, int target)
379 : {
380 165 : InstrPtr q, p = NULL;
381 165 : int i;
382 :
383 2393 : for (i = 1; i < mb->stop; i++) {
384 2393 : q = getInstrPtr(mb, i);
385 2393 : if (q->argv[0] == target && getModuleId(q) == generatorRef && (getFunctionId(q) == parametersRef || getFunctionId(q) == seriesRef))
386 2393 : p = q;
387 2393 : if (q == pci)
388 165 : return p;
389 : }
390 : return p;
391 : }
392 :
393 : #define calculate_range(TPE, TPE2) \
394 : do { \
395 : TPE f, l, s, low, hgh; \
396 : \
397 : f = * getArgReference_##TPE(stk, p, 1); \
398 : l = * getArgReference_##TPE(stk, p, 2); \
399 : if ( p->argc == 3) \
400 : s = f<l? (TPE) 1: (TPE)-1; \
401 : else s = * getArgReference_##TPE(stk, p, 3); \
402 : if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) { \
403 : BBPreclaim(cand); \
404 : throw(MAL, "generator.select", \
405 : SQLSTATE(42000) "Illegal generator range"); \
406 : } \
407 : n = (BUN) (((TPE2) l - (TPE2) f) / (TPE2) s); \
408 : if ((TPE)(n * s + f) != l) \
409 : n++; \
410 : \
411 : low = * getArgReference_##TPE(stk, pci, i); \
412 : hgh = * getArgReference_##TPE(stk, pci, i + 1); \
413 : \
414 : if (!is_##TPE##_nil(low) && low == hgh) \
415 : hi = li; \
416 : if (is_##TPE##_nil(low) && is_##TPE##_nil(hgh)) { \
417 : if (li && hi && !anti) { \
418 : /* match NILs (of which there aren't */ \
419 : /* any) */ \
420 : o1 = o2 = 0; \
421 : } else { \
422 : /* match all non-NIL values, */ \
423 : /* i.e. everything */ \
424 : o1 = 0; \
425 : o2 = (oid) n; \
426 : } \
427 : } else if (s > 0) { \
428 : if (is_##TPE##_nil(low) || low < f) \
429 : o1 = 0; \
430 : else { \
431 : o1 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s); \
432 : if ((TPE) (f + o1 * s) < low || \
433 : (!li && (TPE) (f + o1 * s) == low)) \
434 : o1++; \
435 : } \
436 : if (is_##TPE##_nil(hgh)) \
437 : o2 = (oid) n; \
438 : else if (hgh < f) \
439 : o2 = 0; \
440 : else { \
441 : o2 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s); \
442 : if ((hi && (TPE) (f + o2 * s) == hgh) || \
443 : (TPE) (f + o2 * s) < hgh) \
444 : o2++; \
445 : } \
446 : } else { \
447 : if (is_##TPE##_nil(low)) \
448 : o2 = (oid) n; \
449 : else if (low > f) \
450 : o2 = 0; \
451 : else { \
452 : o2 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s); \
453 : if ((li && (TPE) (f + o2 * s) == low) || \
454 : (TPE) (f + o2 * s) > low) \
455 : o2++; \
456 : } \
457 : if (is_##TPE##_nil(hgh) || hgh > f) \
458 : o1 = 0; \
459 : else { \
460 : o1 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s); \
461 : if ((!hi && (TPE) (f + o1 * s) == hgh) || \
462 : (TPE) (f + o1 * s) > hgh) \
463 : o1++; \
464 : } \
465 : } \
466 : } while (0)
467 :
468 : str
469 0 : VLTgenerator_subselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
470 : {
471 0 : bit li, hi, anti;
472 0 : int i;
473 0 : oid o1, o2;
474 0 : BUN n = 0;
475 0 : BAT *bn, *cand = NULL;
476 0 : struct canditer ci = (struct canditer) {.tpe = cand_dense};
477 0 : InstrPtr p;
478 0 : int tpe;
479 :
480 0 : (void) cntxt;
481 0 : p = findGeneratorDefinition(mb, pci, pci->argv[1]);
482 0 : if (p == NULL)
483 0 : throw(MAL, "generator.select",
484 : SQLSTATE(42000) "Could not locate definition for object");
485 :
486 0 : if (pci->argc == 8) { /* candidate list included */
487 0 : bat candid = *getArgReference_bat(stk, pci, 2);
488 0 : if (candid) {
489 0 : cand = BATdescriptor(candid);
490 0 : if (cand == NULL)
491 0 : throw(MAL, "generator.select",
492 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
493 0 : canditer_init(&ci, NULL, cand);
494 : }
495 : i = 3;
496 : } else
497 : i = 2;
498 :
499 0 : li = * getArgReference_bit(stk, pci, i + 2);
500 0 : hi = * getArgReference_bit(stk, pci, i + 3);
501 0 : anti = * getArgReference_bit(stk, pci, i + 4);
502 :
503 0 : switch ( tpe = getArgType(mb, pci, i)) {
504 0 : case TYPE_bte: calculate_range(bte, sht); break;
505 0 : case TYPE_sht: calculate_range(sht, int); break;
506 0 : case TYPE_int: calculate_range(int, lng); break;
507 : #ifndef HAVE_HGE
508 : case TYPE_lng: calculate_range(lng, lng); break;
509 : #else
510 0 : case TYPE_lng: calculate_range(lng, hge); break;
511 0 : case TYPE_hge: calculate_range(hge, hge); break;
512 : #endif
513 0 : case TYPE_flt: calculate_range(flt, dbl); break;
514 0 : case TYPE_dbl: calculate_range(dbl, dbl); break;
515 0 : default:
516 0 : if (p->argc == 3) {
517 0 : BBPreclaim(cand);
518 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Date step missing");
519 : }
520 0 : if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* months */
521 0 : date tsf,tsl;
522 0 : date tlow,thgh;
523 0 : int tss;
524 0 : oid *ol;
525 :
526 0 : tsf = *getArgReference_TYPE(stk, p, 1, date);
527 0 : tsl = *getArgReference_TYPE(stk, p, 2, date);
528 0 : tss = *getArgReference_int(stk, p, 3);
529 0 : if ( tss == 0 ||
530 0 : is_date_nil(tsf) || is_date_nil(tsl) ||
531 0 : (tss > 0 && tsf > tsl ) ||
532 0 : (tss < 0 && tsf < tsl )
533 : ) {
534 0 : BBPreclaim(cand);
535 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
536 : }
537 :
538 0 : tlow = *getArgReference_TYPE(stk,pci,i, date);
539 0 : thgh = *getArgReference_TYPE(stk,pci,i+1, date);
540 :
541 0 : if (!is_date_nil(tlow) && tlow == thgh)
542 0 : hi = li;
543 0 : if( hi && !is_date_nil(thgh)) {
544 0 : thgh = date_add_month(thgh, 1);
545 0 : if (is_date_nil(thgh)) {
546 0 : BBPreclaim(cand);
547 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
548 : }
549 : }
550 0 : if( !li && !is_date_nil(tlow)) {
551 0 : tlow = date_add_month(tlow, 1);
552 0 : if (is_date_nil(tlow)) {
553 0 : BBPreclaim(cand);
554 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
555 : }
556 : }
557 :
558 0 : o2 = (BUN) (date_diff(tsl, tsf) / (tss*28));
559 0 : bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
560 0 : if (bn == NULL) {
561 0 : BBPreclaim(cand);
562 0 : throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
563 : }
564 :
565 : // simply enumerate the sequence and filter it by predicate and candidate list
566 0 : ol = (oid *) Tloc(bn, 0);
567 0 : for (o1=0; o1 <= o2; o1++) {
568 0 : if(((is_date_nil(tlow) || tsf >= tlow) &&
569 0 : (is_date_nil(thgh) || tsf < thgh)) != anti ){
570 : /* could be improved when no candidate list is available into a void/void BAT */
571 0 : if( cand == NULL || canditer_contains(&ci, o1)) {
572 0 : *ol++ = o1;
573 0 : n++;
574 : }
575 : }
576 0 : tsf = date_add_month(tsf, tss);
577 0 : if (is_date_nil(tsf)) {
578 0 : BBPreclaim(cand);
579 0 : BBPreclaim(bn);
580 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
581 : }
582 : }
583 0 : BBPreclaim(cand);
584 0 : BATsetcount(bn, n);
585 0 : bn->tsorted = true;
586 0 : bn->trevsorted = BATcount(bn) <= 1;
587 0 : bn->tkey = true;
588 0 : bn->tnil = false;
589 0 : bn->tnonil = true;
590 0 : * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
591 0 : BBPkeepref(bn);
592 0 : return MAL_SUCCEED;
593 0 : } else if (tpe == TYPE_date) { /* days */
594 0 : date tsf,tsl;
595 0 : date tlow,thgh;
596 0 : lng tss;
597 0 : oid *ol;
598 :
599 0 : tsf = *getArgReference_TYPE(stk, p, 1, date);
600 0 : tsl = *getArgReference_TYPE(stk, p, 2, date);
601 0 : tss = *getArgReference_lng(stk, p, 3);
602 0 : if ( tss == 0 ||
603 0 : is_date_nil(tsf) || is_date_nil(tsl) ||
604 0 : (tss > 0 && tsf > tsl ) ||
605 0 : (tss < 0 && tsf < tsl )
606 : ) {
607 0 : BBPreclaim(cand);
608 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
609 : }
610 0 : tss /= 24*60*60*1000;
611 :
612 0 : tlow = *getArgReference_TYPE(stk,pci,i, date);
613 0 : thgh = *getArgReference_TYPE(stk,pci,i+1, date);
614 :
615 0 : if (!is_date_nil(tlow) && tlow == thgh)
616 0 : hi = li;
617 0 : if( hi && !is_date_nil(thgh)) {
618 0 : thgh = date_add_month(thgh, 1);
619 0 : if (is_date_nil(thgh)) {
620 0 : BBPreclaim(cand);
621 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
622 : }
623 : }
624 0 : if( !li && !is_date_nil(tlow)) {
625 0 : tlow = date_add_month(tlow, 1);
626 0 : if (is_date_nil(tlow)) {
627 0 : BBPreclaim(cand);
628 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
629 : }
630 : }
631 :
632 0 : o2 = (BUN) (date_diff(tsl, tsf) / tss) + 1;
633 0 : bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
634 0 : if (bn == NULL) {
635 0 : BBPreclaim(cand);
636 0 : throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
637 : }
638 :
639 : // simply enumerate the sequence and filter it by predicate and candidate list
640 0 : ol = (oid *) Tloc(bn, 0);
641 0 : for (o1=0; o1 <= o2; o1++) {
642 0 : if(((is_date_nil(tlow) || tsf >= tlow) &&
643 0 : (is_date_nil(thgh) || tsf < thgh)) != anti ){
644 : /* could be improved when no candidate list is available into a void/void BAT */
645 0 : if( cand == NULL || canditer_contains(&ci, o1)) {
646 0 : *ol++ = o1;
647 0 : n++;
648 : }
649 : }
650 0 : tsf = date_add_day(tsf, (int) tss);
651 0 : if (is_date_nil(tsf)) {
652 0 : BBPreclaim(cand);
653 0 : BBPreclaim(bn);
654 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
655 : }
656 : }
657 0 : BBPreclaim(cand);
658 0 : BATsetcount(bn, n);
659 0 : bn->tsorted = true;
660 0 : bn->trevsorted = BATcount(bn) <= 1;
661 0 : bn->tkey = true;
662 0 : bn->tnil = false;
663 0 : bn->tnonil = true;
664 0 : * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
665 0 : BBPkeepref(bn);
666 0 : return MAL_SUCCEED;
667 0 : } else if (tpe == TYPE_timestamp) {
668 0 : timestamp tsf,tsl;
669 0 : timestamp tlow,thgh;
670 0 : lng tss;
671 0 : oid *ol;
672 :
673 0 : tsf = *getArgReference_TYPE(stk, p, 1, timestamp);
674 0 : tsl = *getArgReference_TYPE(stk, p, 2, timestamp);
675 0 : if (p->argc == 3) {
676 0 : BBPreclaim(cand);
677 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
678 : }
679 0 : tss = *getArgReference_lng(stk, p, 3);
680 0 : if ( tss == 0 ||
681 0 : is_timestamp_nil(tsf) || is_timestamp_nil(tsl) ||
682 0 : (tss > 0 && tsf > tsl ) ||
683 0 : (tss < 0 && tsf < tsl )
684 : ) {
685 0 : BBPreclaim(cand);
686 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
687 : }
688 :
689 0 : tlow = *getArgReference_TYPE(stk,pci,i, timestamp);
690 0 : thgh = *getArgReference_TYPE(stk,pci,i+1, timestamp);
691 :
692 0 : if (!is_timestamp_nil(tlow) && tlow == thgh)
693 0 : hi = li;
694 0 : if( hi && !is_timestamp_nil(thgh)) {
695 0 : thgh = timestamp_add_usec(thgh, 1);
696 0 : if (is_timestamp_nil(thgh)) {
697 0 : BBPreclaim(cand);
698 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
699 : }
700 : }
701 0 : if( !li && !is_timestamp_nil(tlow)) {
702 0 : tlow = timestamp_add_usec(tlow, 1);
703 0 : if (is_timestamp_nil(tlow)) {
704 0 : BBPreclaim(cand);
705 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
706 : }
707 : }
708 :
709 : /* casting one value to lng causes the whole
710 : * computation to be done as lng, reducing the
711 : * risk of overflow */
712 0 : tss *= 1000; /* msec -> usec */
713 0 : o2 = (BUN) (timestamp_diff(tsl, tsf) / tss);
714 0 : bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
715 0 : if (bn == NULL) {
716 0 : BBPreclaim(cand);
717 0 : throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
718 : }
719 :
720 : // simply enumerate the sequence and filter it by predicate and candidate list
721 0 : ol = (oid *) Tloc(bn, 0);
722 0 : for (o1=0; o1 <= o2; o1++) {
723 0 : if(((is_timestamp_nil(tlow) || tsf >= tlow) &&
724 0 : (is_timestamp_nil(thgh) || tsf < thgh)) != anti ){
725 : /* could be improved when no candidate list is available into a void/void BAT */
726 0 : if( cand == NULL || canditer_contains(&ci, o1)) {
727 0 : *ol++ = o1;
728 0 : n++;
729 : }
730 : }
731 0 : tsf = timestamp_add_usec(tsf, tss);
732 0 : if (is_timestamp_nil(tsf)) {
733 0 : BBPreclaim(cand);
734 0 : BBPreclaim(bn);
735 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
736 : }
737 : }
738 0 : BBPreclaim(cand);
739 0 : BATsetcount(bn, n);
740 0 : bn->tsorted = true;
741 0 : bn->trevsorted = BATcount(bn) <= 1;
742 0 : bn->tkey = true;
743 0 : bn->tnil = false;
744 0 : bn->tnonil = true;
745 0 : * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
746 0 : BBPkeepref(bn);
747 0 : return MAL_SUCCEED;
748 : } else {
749 0 : BBPreclaim(cand);
750 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Unsupported type in select");
751 : }
752 : }
753 0 : if (o1 > (oid) n)
754 : o1 = (oid) n;
755 0 : if (o2 > (oid) n)
756 : o2 = (oid) n;
757 0 : assert(o1 <= o2);
758 0 : assert(o2 - o1 <= (oid) n);
759 0 : if (anti && o1 == o2) {
760 0 : o1 = 0;
761 0 : o2 = (oid) n;
762 0 : anti = 0;
763 : }
764 0 : if (cand) {
765 0 : if (anti) {
766 0 : bn = canditer_slice2val(&ci, oid_nil, o1, o2, oid_nil);
767 : } else {
768 0 : bn = canditer_sliceval(&ci, o1, o2);
769 : }
770 0 : BBPunfix(cand->batCacheid);
771 0 : if (bn == NULL)
772 0 : throw(MAL, "generator.select",
773 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
774 : } else {
775 0 : if (anti) {
776 0 : oid o;
777 0 : oid *op;
778 :
779 0 : bn = COLnew(0, TYPE_oid, n - (o2 - o1), TRANSIENT);
780 0 : if (bn == NULL)
781 0 : throw(MAL, "generator.select",
782 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
783 0 : BATsetcount(bn, n - (o2 - o1));
784 0 : op = (oid *) Tloc(bn, 0);
785 0 : for (o = 0; o < o1; o++)
786 0 : *op++ = o;
787 0 : for (o = o2; o < (oid) n; o++)
788 0 : *op++ = o;
789 0 : bn->tnil = false;
790 0 : bn->tnonil = true;
791 0 : bn->tsorted = true;
792 0 : bn->trevsorted = BATcount(bn) <= 1;
793 0 : bn->tkey = true;
794 : } else {
795 0 : bn = BATdense(0, o1, (BUN) (o2 - o1));
796 0 : if (bn == NULL)
797 0 : throw(MAL, "generator.select",
798 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
799 : }
800 : }
801 0 : * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
802 0 : BBPkeepref(bn);
803 0 : return MAL_SUCCEED;
804 : }
805 :
806 : #define PREVVALUEbte(x) ((x) - 1)
807 : #define PREVVALUEsht(x) ((x) - 1)
808 : #define PREVVALUEint(x) ((x) - 1)
809 : #define PREVVALUElng(x) ((x) - 1)
810 : #ifdef HAVE_HGE
811 : #define PREVVALUEhge(x) ((x) - 1)
812 : #endif
813 : #define PREVVALUEoid(x) ((x) - 1)
814 : #define PREVVALUEflt(x) nextafterf((x), -GDK_flt_max)
815 : #define PREVVALUEdbl(x) nextafter((x), -GDK_dbl_max)
816 :
817 : #define NEXTVALUEbte(x) ((x) + 1)
818 : #define NEXTVALUEsht(x) ((x) + 1)
819 : #define NEXTVALUEint(x) ((x) + 1)
820 : #define NEXTVALUElng(x) ((x) + 1)
821 : #ifdef HAVE_HGE
822 : #define NEXTVALUEhge(x) ((x) + 1)
823 : #endif
824 : #define NEXTVALUEoid(x) ((x) + 1)
825 : #define NEXTVALUEflt(x) nextafterf((x), GDK_flt_max)
826 : #define NEXTVALUEdbl(x) nextafter((x), GDK_dbl_max)
827 :
828 : #define HGE_ABS(a) (((a) < 0) ? -(a) : (a))
829 :
830 : #define VLTthetasubselect(TPE,ABS) \
831 : do { \
832 : TPE f,l,s, low, hgh; \
833 : BUN j; oid *v; \
834 : f = *getArgReference_##TPE(stk,p, 1); \
835 : l = *getArgReference_##TPE(stk,p, 2); \
836 : if ( p->argc == 3) \
837 : s = f<l? (TPE) 1: (TPE)-1; \
838 : else s = *getArgReference_##TPE(stk,p, 3); \
839 : if( s == 0 || (f<l && s < 0) || (f>l && s> 0)) { \
840 : BBPreclaim(cand); \
841 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal range"); \
842 : } \
843 : cap = (BUN)(ABS(l-f)/ABS(s)); \
844 : bn = COLnew(0, TYPE_oid, cap, TRANSIENT); \
845 : if( bn == NULL) { \
846 : BBPreclaim(cand); \
847 : throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
848 : } \
849 : low= hgh = TPE##_nil; \
850 : v = (oid*) Tloc(bn,0); \
851 : if ( strcmp(oper,"<") == 0){ \
852 : hgh= *getArgReference_##TPE(stk,pci,3); \
853 : hgh = PREVVALUE##TPE(hgh); \
854 : } else if ( strcmp(oper,"<=") == 0){ \
855 : hgh= *getArgReference_##TPE(stk,pci,3); \
856 : } else if ( strcmp(oper,">") == 0){ \
857 : low= *getArgReference_##TPE(stk,pci,3); \
858 : low = NEXTVALUE##TPE(low); \
859 : } else if ( strcmp(oper,">=") == 0){ \
860 : low= *getArgReference_##TPE(stk,pci,3); \
861 : } else if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){ \
862 : hgh= low= *getArgReference_##TPE(stk,pci,3); \
863 : anti = 1; \
864 : } else if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){ \
865 : hgh= low= *getArgReference_##TPE(stk,pci,3); \
866 : } else { \
867 : BBPreclaim(cand); \
868 : BBPreclaim(bn); \
869 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator"); \
870 : } \
871 : for(j=0;j<cap;j++, f+=s, o++) \
872 : if( ((is_##TPE##_nil(low) || f >= low) && (is_##TPE##_nil(hgh) || f <= hgh)) != anti){ \
873 : if(cand == NULL || canditer_contains(&ci, o)) { \
874 : *v++ = o; \
875 : c++; \
876 : } \
877 : } \
878 : } while (0)
879 :
880 :
881 29 : str VLTgenerator_thetasubselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
882 : {
883 29 : int anti =0,tpe;
884 29 : bat cndid =0;
885 29 : BAT *cand = 0, *bn = NULL;
886 29 : struct canditer ci = (struct canditer) {.tpe = cand_dense};
887 29 : BUN cap,j, c = 0;
888 29 : oid o = 0;
889 29 : InstrPtr p;
890 29 : str oper;
891 :
892 29 : (void) cntxt;
893 29 : p = findGeneratorDefinition(mb,pci,pci->argv[1]);
894 29 : if( p == NULL)
895 0 : throw(MAL,"generator.thetaselect",SQLSTATE(42000) "Could not locate definition for object");
896 :
897 29 : assert(pci->argc == 5); // candidate list included
898 29 : cndid = *getArgReference_bat(stk,pci, 2);
899 29 : if( !is_bat_nil(cndid)){
900 2 : cand = BATdescriptor(cndid);
901 2 : if( cand == NULL)
902 0 : throw(MAL,"generator.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
903 2 : canditer_init(&ci, NULL, cand);
904 : }
905 29 : oper= *getArgReference_str(stk,pci,4);
906 :
907 : // check the step direction
908 :
909 29 : switch( tpe =getArgType(mb,pci,3)){
910 119 : case TYPE_bte: VLTthetasubselect(bte,abs);break;
911 0 : case TYPE_sht: VLTthetasubselect(sht,abs);break;
912 0 : case TYPE_int: VLTthetasubselect(int,abs);break;
913 16 : case TYPE_lng: VLTthetasubselect(lng,llabs);break;
914 : #ifdef HAVE_HGE
915 0 : case TYPE_hge: VLTthetasubselect(hge,HGE_ABS);break;
916 : #endif
917 8 : case TYPE_flt: VLTthetasubselect(flt,fabsf);break;
918 25 : case TYPE_dbl: VLTthetasubselect(dbl,fabs);break;
919 11 : default:
920 11 : if (tpe == TYPE_date && p->argc == 3) {
921 0 : BBPreclaim(cand);
922 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
923 : }
924 2 : if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* months */
925 1 : date f,l, val, low, hgh;
926 1 : int s;
927 1 : oid *v;
928 :
929 1 : f = *getArgReference_TYPE(stk,p, 1, date);
930 1 : l = *getArgReference_TYPE(stk,p, 2, date);
931 1 : s = *getArgReference_int(stk,p, 3);
932 1 : if ( s == 0 ||
933 1 : (s > 0 && f > l) ||
934 1 : (s < 0 && f < l)
935 : ) {
936 0 : BBPreclaim(cand);
937 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
938 : }
939 :
940 1 : hgh = low = date_nil;
941 1 : if ( strcmp(oper,"<") == 0){
942 1 : hgh= *getArgReference_TYPE(stk,pci,3, date);
943 1 : hgh = date_add_month(hgh, -1);
944 1 : if (is_date_nil(hgh)) {
945 0 : BBPreclaim(cand);
946 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
947 : }
948 : } else
949 0 : if ( strcmp(oper,"<=") == 0){
950 0 : hgh= *getArgReference_TYPE(stk,pci,3, date) ;
951 : } else
952 0 : if ( strcmp(oper,">") == 0){
953 0 : low= *getArgReference_TYPE(stk,pci,3, date);
954 0 : low = date_add_month(low, 1);
955 0 : if (is_date_nil(low)) {
956 0 : BBPreclaim(cand);
957 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
958 : }
959 : } else
960 0 : if ( strcmp(oper,">=") == 0){
961 0 : low= *getArgReference_TYPE(stk,pci,3, date);
962 : } else
963 0 : if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
964 0 : hgh= low= *getArgReference_TYPE(stk,pci,3, date);
965 0 : anti = 1;
966 : } else
967 0 : if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
968 0 : hgh= low= *getArgReference_TYPE(stk,pci,3, date);
969 : } else {
970 0 : BBPreclaim(cand);
971 0 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
972 : }
973 :
974 1 : cap = (BUN) (date_diff(l, f) / (s*28));
975 1 : bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
976 1 : if( bn == NULL) {
977 0 : BBPreclaim(cand);
978 0 : throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
979 : }
980 1 : v = (oid*) Tloc(bn,0);
981 :
982 1 : val = f;
983 14 : for(j = 0; j< cap; j++, o++){
984 26 : if (((is_date_nil(low) || val >= low) &&
985 13 : (is_date_nil(hgh) || val <= hgh)) != anti){
986 5 : if(cand == NULL || canditer_contains(&ci, o)){
987 5 : *v++ = o;
988 5 : c++;
989 : }
990 : }
991 13 : val = date_add_month(val, s);
992 13 : if (is_date_nil(val)) {
993 0 : BBPreclaim(cand);
994 0 : BBPreclaim(bn);
995 0 : throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
996 : }
997 : }
998 1 : } else if (tpe == TYPE_date) { /* days */
999 1 : date f,l, val, low, hgh;
1000 1 : lng s;
1001 1 : oid *v;
1002 :
1003 1 : f = *getArgReference_TYPE(stk,p, 1, date);
1004 1 : l = *getArgReference_TYPE(stk,p, 2, date);
1005 1 : s = *getArgReference_lng(stk,p, 3);
1006 1 : if ( s == 0 ||
1007 1 : (s > 0 && f > l) ||
1008 1 : (s < 0 && f < l)
1009 : ) {
1010 0 : BBPreclaim(cand);
1011 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
1012 : }
1013 1 : s /= 24*60*60*1000;
1014 :
1015 1 : hgh = low = date_nil;
1016 1 : if ( strcmp(oper,"<") == 0){
1017 1 : hgh= *getArgReference_TYPE(stk,pci,3, date);
1018 1 : hgh = date_add_day(hgh, -1);
1019 1 : if (is_date_nil(hgh)) {
1020 0 : BBPreclaim(cand);
1021 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
1022 : }
1023 : } else
1024 0 : if ( strcmp(oper,"<=") == 0){
1025 0 : hgh= *getArgReference_TYPE(stk,pci,3, date) ;
1026 : } else
1027 0 : if ( strcmp(oper,">") == 0){
1028 0 : low= *getArgReference_TYPE(stk,pci,3, date);
1029 0 : low = date_add_month(low, 1);
1030 0 : if (is_date_nil(low)) {
1031 0 : BBPreclaim(cand);
1032 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
1033 : }
1034 : } else
1035 0 : if ( strcmp(oper,">=") == 0){
1036 0 : low= *getArgReference_TYPE(stk,pci,3, date);
1037 : } else
1038 0 : if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
1039 0 : hgh= low= *getArgReference_TYPE(stk,pci,3, date);
1040 0 : anti = 1;
1041 : } else
1042 0 : if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
1043 0 : hgh= low= *getArgReference_TYPE(stk,pci,3, date);
1044 : } else {
1045 0 : BBPreclaim(cand);
1046 0 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
1047 : }
1048 :
1049 1 : cap = (BUN) (date_diff(l, f) / s) + 1;
1050 1 : bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
1051 1 : if( bn == NULL) {
1052 0 : BBPreclaim(cand);
1053 0 : throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1054 : }
1055 1 : v = (oid*) Tloc(bn,0);
1056 :
1057 1 : val = f;
1058 26 : for(j = 0; j< cap; j++, o++){
1059 50 : if (((is_date_nil(low) || val >= low) &&
1060 25 : (is_date_nil(hgh) || val <= hgh)) != anti){
1061 11 : if(cand == NULL || canditer_contains(&ci, o)){
1062 11 : *v++ = o;
1063 11 : c++;
1064 : }
1065 : }
1066 25 : val = date_add_day(val, (int) s);
1067 25 : if (is_date_nil(val)) {
1068 0 : BBPreclaim(cand);
1069 0 : BBPreclaim(bn);
1070 0 : throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
1071 : }
1072 : }
1073 9 : } else if ( tpe == TYPE_timestamp){
1074 9 : timestamp f,l, val, low, hgh;
1075 9 : lng s;
1076 9 : oid *v;
1077 :
1078 9 : f = *getArgReference_TYPE(stk,p, 1, timestamp);
1079 9 : l = *getArgReference_TYPE(stk,p, 2, timestamp);
1080 9 : if ( p->argc == 3) {
1081 0 : BBPreclaim(cand);
1082 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
1083 : }
1084 9 : s = *getArgReference_lng(stk,p, 3);
1085 9 : if ( s == 0 ||
1086 9 : (s > 0 && f > l) ||
1087 9 : (s < 0 && f < l)
1088 : ) {
1089 0 : BBPreclaim(cand);
1090 0 : throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
1091 : }
1092 :
1093 9 : hgh = low = timestamp_nil;
1094 9 : if ( strcmp(oper,"<") == 0){
1095 5 : hgh= *getArgReference_TYPE(stk,pci,3, timestamp);
1096 5 : hgh = timestamp_add_usec(hgh, -1);
1097 5 : if (is_timestamp_nil(hgh)) {
1098 0 : BBPreclaim(cand);
1099 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
1100 : }
1101 : } else
1102 4 : if ( strcmp(oper,"<=") == 0){
1103 0 : hgh= *getArgReference_TYPE(stk,pci,3, timestamp) ;
1104 : } else
1105 4 : if ( strcmp(oper,">") == 0){
1106 3 : low= *getArgReference_TYPE(stk,pci,3, timestamp);
1107 3 : low = timestamp_add_usec(low, 1);
1108 3 : if (is_timestamp_nil(low)) {
1109 0 : BBPreclaim(cand);
1110 0 : throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
1111 : }
1112 : } else
1113 1 : if ( strcmp(oper,">=") == 0){
1114 0 : low= *getArgReference_TYPE(stk,pci,3, timestamp);
1115 : } else
1116 1 : if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
1117 0 : hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
1118 0 : anti = 1;
1119 : } else
1120 1 : if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
1121 1 : hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
1122 : } else {
1123 0 : BBPreclaim(cand);
1124 0 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
1125 : }
1126 :
1127 9 : s *= 1000; /* msec -> usec */
1128 9 : cap = (BUN) (timestamp_diff(l, f) / s);
1129 9 : bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
1130 9 : if( bn == NULL) {
1131 0 : BBPreclaim(cand);
1132 0 : throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1133 : }
1134 9 : v = (oid*) Tloc(bn,0);
1135 :
1136 9 : val = f;
1137 85 : for(j = 0; j< cap; j++, o++){
1138 148 : if (((is_timestamp_nil(low) || val >= low) &&
1139 50 : (is_timestamp_nil(hgh) || val <= hgh)) != anti){
1140 34 : if(cand == NULL || canditer_contains(&ci, o)){
1141 31 : *v++ = o;
1142 31 : c++;
1143 : }
1144 : }
1145 76 : val = timestamp_add_usec(val, s);
1146 76 : if (is_timestamp_nil(val)) {
1147 0 : BBPreclaim(cand);
1148 0 : BBPreclaim(bn);
1149 0 : throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
1150 : }
1151 : }
1152 : } else {
1153 0 : BBPreclaim(cand);
1154 0 : throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal generator arguments");
1155 : }
1156 : }
1157 :
1158 29 : if( cndid)
1159 29 : BBPunfix(cndid);
1160 29 : BATsetcount(bn,c);
1161 29 : bn->tsorted = true;
1162 29 : bn->trevsorted = false;
1163 29 : bn->tkey = true;
1164 29 : bn->tnil = false;
1165 29 : bn->tnonil = true;
1166 29 : *getArgReference_bat(stk,pci,0) = bn->batCacheid;
1167 29 : BBPkeepref(bn);
1168 29 : return MAL_SUCCEED;
1169 : }
1170 :
1171 : #define VLTprojection(TPE) \
1172 : do { \
1173 : TPE f,l,s, val; \
1174 : TPE *v; \
1175 : f = *getArgReference_##TPE(stk,p, 1); \
1176 : l = *getArgReference_##TPE(stk,p, 2); \
1177 : if ( p->argc == 3) \
1178 : s = f<l? (TPE) 1: (TPE)-1; \
1179 : else \
1180 : s = * getArgReference_##TPE(stk, p, 3); \
1181 : if ( s == 0 || (f> l && s>0) || (f<l && s < 0)) { \
1182 : BBPunfix(b->batCacheid); \
1183 : throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range"); \
1184 : } \
1185 : bn = COLnew(0, TYPE_##TPE, cnt, TRANSIENT); \
1186 : if( bn == NULL){ \
1187 : BBPunfix(b->batCacheid); \
1188 : throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
1189 : } \
1190 : v = (TPE*) Tloc(bn,0); \
1191 : for(; cnt-- > 0; o++){ \
1192 : val = f + ((TPE) (ol == NULL ? o : ol[o])) * s; \
1193 : if ( (s > 0 && (val < f || val >= l)) || (s < 0 && (val <= l || val > f))) \
1194 : continue; \
1195 : *v++ = val; \
1196 : c++; \
1197 : } \
1198 : } while (0)
1199 :
1200 136 : str VLTgenerator_projection(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1201 : {
1202 136 : int tpe;
1203 136 : bat *ret;
1204 136 : BAT *b, *bn = NULL;
1205 136 : BUN cnt, c = 0;
1206 136 : oid *ol = NULL, o= 0;
1207 136 : InstrPtr p;
1208 :
1209 136 : (void) cntxt;
1210 136 : p = findGeneratorDefinition(mb,pci,pci->argv[2]);
1211 :
1212 136 : ret = getArgReference_bat(stk,pci,0);
1213 136 : b = BATdescriptor(*getArgReference_bat(stk,pci,1));
1214 136 : if( b == NULL)
1215 0 : throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1216 :
1217 : // if it does not exist we should fall back to the ordinary projection to try
1218 : // it might have been materialized already
1219 136 : if( p == NULL){
1220 0 : bn = BATdescriptor( *getArgReference_bat(stk,pci,2));
1221 0 : if( bn == NULL) {
1222 0 : BBPunfix(b->batCacheid);
1223 0 : throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1224 : }
1225 0 : BAT *bp = BATproject(b, bn);
1226 0 : BBPunfix(b->batCacheid);
1227 0 : BBPunfix(bn->batCacheid);
1228 0 : if (bp == NULL)
1229 0 : throw(MAL, "generator.projection", GDK_EXCEPTION);
1230 0 : *ret = bp->batCacheid;
1231 0 : BBPkeepref(bp);
1232 0 : return MAL_SUCCEED;
1233 : }
1234 :
1235 136 : cnt = BATcount(b);
1236 136 : if ( b->ttype == TYPE_void)
1237 52 : o = b->tseqbase;
1238 : else
1239 84 : ol = (oid*) Tloc(b,0);
1240 :
1241 : /* the actual code to perform a projection over generators */
1242 136 : switch( tpe = getArgType(mb,p,1)){
1243 431 : case TYPE_bte: VLTprojection(bte); break;
1244 999008 : case TYPE_sht: VLTprojection(sht); break;
1245 1149348 : case TYPE_int: VLTprojection(int); break;
1246 14 : case TYPE_lng: VLTprojection(lng); break;
1247 : #ifdef HAVE_HGE
1248 0 : case TYPE_hge: VLTprojection(hge); break;
1249 : #endif
1250 7 : case TYPE_flt: VLTprojection(flt); break;
1251 17 : case TYPE_dbl: VLTprojection(dbl); break;
1252 37 : default:
1253 37 : if (tpe == TYPE_date && p->argc == 3) {
1254 0 : BBPunfix(b->batCacheid);
1255 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
1256 : }
1257 2 : if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* months */
1258 1 : date f,l, val;
1259 1 : int s,t;
1260 1 : date *v;
1261 1 : f = *getArgReference_TYPE(stk,p, 1, date);
1262 1 : l = *getArgReference_TYPE(stk,p, 2, date);
1263 1 : s = *getArgReference_int(stk,p, 3);
1264 1 : if ( s == 0 ||
1265 1 : (s< 0 && f < l) ||
1266 1 : (s> 0 && l < f) ) {
1267 0 : BBPunfix(b->batCacheid);
1268 0 : throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
1269 : }
1270 :
1271 1 : bn = COLnew(0, TYPE_date, cnt, TRANSIENT);
1272 1 : if( bn == NULL){
1273 0 : BBPunfix(b->batCacheid);
1274 0 : throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1275 : }
1276 :
1277 1 : v = (date*) Tloc(bn,0);
1278 :
1279 6 : for(; cnt-- > 0; o++){
1280 5 : t = ((int) (ol == NULL ? o : ol[o])) * s;
1281 5 : val = date_add_month(f, t);
1282 5 : if (is_date_nil(val)) {
1283 0 : BBPunfix(b->batCacheid);
1284 0 : BBPreclaim(bn);
1285 0 : throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
1286 : }
1287 :
1288 5 : if ( is_date_nil(val))
1289 : continue;
1290 5 : if (s > 0 && (val < f || val >= l) )
1291 0 : continue;
1292 5 : if (s < 0 && (val <= l || val > f) )
1293 0 : continue;
1294 5 : *v++ = val;
1295 5 : c++;
1296 : }
1297 1 : } else if (tpe == TYPE_date) { /* days */
1298 1 : date f,l, val;
1299 1 : lng s,t;
1300 1 : date *v;
1301 1 : f = *getArgReference_TYPE(stk,p, 1, date);
1302 1 : l = *getArgReference_TYPE(stk,p, 2, date);
1303 1 : s = *getArgReference_lng(stk,p, 3);
1304 1 : if ( s == 0 ||
1305 1 : (s< 0 && f < l) ||
1306 1 : (s> 0 && l < f) ) {
1307 0 : BBPunfix(b->batCacheid);
1308 0 : throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
1309 : }
1310 1 : s /= 24*60*60*1000;
1311 :
1312 1 : bn = COLnew(0, TYPE_date, cnt, TRANSIENT);
1313 1 : if( bn == NULL){
1314 0 : BBPunfix(b->batCacheid);
1315 0 : throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1316 : }
1317 :
1318 1 : v = (date*) Tloc(bn,0);
1319 :
1320 12 : for(; cnt-- > 0; o++){
1321 11 : t = ((int) (ol == NULL ? o : ol[o])) * s;
1322 11 : val = date_add_day(f, (int) t);
1323 11 : if (is_date_nil(val)) {
1324 0 : BBPunfix(b->batCacheid);
1325 0 : BBPreclaim(bn);
1326 0 : throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
1327 : }
1328 :
1329 11 : if ( is_date_nil(val))
1330 : continue;
1331 11 : if (s > 0 && (val < f || val >= l) )
1332 0 : continue;
1333 11 : if (s < 0 && (val <= l || val > f) )
1334 0 : continue;
1335 11 : *v++ = val;
1336 11 : c++;
1337 : }
1338 35 : } else if ( tpe == TYPE_timestamp){
1339 35 : timestamp f,l, val;
1340 35 : lng s,t;
1341 35 : timestamp *v;
1342 35 : f = *getArgReference_TYPE(stk,p, 1, timestamp);
1343 35 : l = *getArgReference_TYPE(stk,p, 2, timestamp);
1344 35 : if ( p->argc == 3) {
1345 0 : BBPunfix(b->batCacheid);
1346 0 : throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
1347 : }
1348 35 : s = *getArgReference_lng(stk,p, 3);
1349 35 : if ( s == 0 ||
1350 35 : (s< 0 && f < l) ||
1351 35 : (s> 0 && l < f) ) {
1352 0 : BBPunfix(b->batCacheid);
1353 0 : throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
1354 : }
1355 :
1356 35 : s *= 1000; /* msec -> usec */
1357 35 : bn = COLnew(0, TYPE_timestamp, cnt, TRANSIENT);
1358 35 : if( bn == NULL){
1359 0 : BBPunfix(b->batCacheid);
1360 0 : throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1361 : }
1362 :
1363 35 : v = (timestamp*) Tloc(bn,0);
1364 :
1365 89 : for(; cnt-- > 0; o++){
1366 54 : t = ((lng) (ol == NULL ? o : ol[o])) * s;
1367 54 : val = timestamp_add_usec(f, t);
1368 54 : if (is_timestamp_nil(val)) {
1369 0 : BBPunfix(b->batCacheid);
1370 0 : BBPreclaim(bn);
1371 0 : throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
1372 : }
1373 :
1374 54 : if ( is_timestamp_nil(val))
1375 : continue;
1376 54 : if (s > 0 && (val < f || val >= l) )
1377 0 : continue;
1378 54 : if (s < 0 && (val <= l || val > f) )
1379 0 : continue;
1380 54 : *v++ = val;
1381 54 : c++;
1382 : }
1383 : }
1384 : }
1385 :
1386 : /* administrative wrapup of the projection */
1387 136 : BBPunfix(b->batCacheid);
1388 136 : if( bn){
1389 136 : BATsetcount(bn,c);
1390 136 : bn->tsorted = bn->trevsorted = false;
1391 136 : bn->tkey = false;
1392 136 : bn->tnil = false;
1393 136 : bn->tnonil = false;
1394 136 : *getArgReference_bat(stk,pci,0) = bn->batCacheid;
1395 136 : BBPkeepref(bn);
1396 : }
1397 : return MAL_SUCCEED;
1398 : }
1399 :
1400 : /* The operands of a join operation can either be defined on a generator */
1401 : #define VLTjoin(TPE, ABS) \
1402 : do { \
1403 : TPE f,l,s; TPE *v; BUN w; \
1404 : f = *getArgReference_##TPE(stk,p, 1); \
1405 : l = *getArgReference_##TPE(stk,p, 2); \
1406 : if ( p->argc == 3) \
1407 : s = f<l? (TPE) 1: (TPE)-1; \
1408 : else \
1409 : s = * getArgReference_##TPE(stk, p, 3); \
1410 : incr = s > 0; \
1411 : v = (TPE*) Tloc(b,0); \
1412 : if ( s == 0 || (f> l && s>0) || (f<l && s < 0)) { \
1413 : BBPunfix(bln->batCacheid); \
1414 : BBPunfix(brn->batCacheid); \
1415 : BBPreclaim(bl); \
1416 : BBPreclaim(br); \
1417 : throw(MAL,"generator.join", SQLSTATE(42000) "Illegal range"); \
1418 : } \
1419 : for( ; cnt >0; cnt--,o++,v++){ \
1420 : w = (BUN) (ABS(*v -f)/ABS(s)); \
1421 : if ( f + (TPE)(w * s) == *v ){ \
1422 : *ol++ = (oid) w; \
1423 : *or++ = o; \
1424 : c++; \
1425 : } \
1426 : } \
1427 : } while (0)
1428 :
1429 0 : str VLTgenerator_join(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1430 : {
1431 0 : BAT *b, *bl = NULL, *br = NULL, *bln = NULL, *brn= NULL;
1432 0 : BUN cnt,c =0;
1433 0 : oid o= 0, *ol, *or;
1434 0 : int tpe, incr=0, materialized = 0;
1435 0 : InstrPtr p = NULL, q = NULL;
1436 0 : str msg = MAL_SUCCEED;
1437 :
1438 0 : (void) cntxt;
1439 : // we assume at most one of the arguments to refer to the generator
1440 0 : p = findGeneratorDefinition(mb,pci,pci->argv[2]);
1441 0 : q = findGeneratorDefinition(mb,pci,pci->argv[3]);
1442 :
1443 0 : if (p == NULL && q == NULL) {
1444 0 : bl = BATdescriptor(*getArgReference_bat(stk, pci, 2));
1445 0 : br = BATdescriptor(*getArgReference_bat(stk, pci, 3));
1446 0 : if (bl == NULL || br == NULL) {
1447 0 : BBPreclaim(bl);
1448 0 : BBPreclaim(br);
1449 0 : throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1450 : }
1451 0 : gdk_return rc = BATjoin(&bln, &brn, bl, br, NULL, NULL, false, BUN_NONE);
1452 0 : BBPunfix(bl->batCacheid);
1453 0 : BBPunfix(br->batCacheid);
1454 0 : if (rc != GDK_SUCCEED)
1455 0 : throw(MAL,"generator.join", GDK_EXCEPTION);
1456 0 : *getArgReference_bat(stk, pci, 0) = bln->batCacheid;
1457 0 : *getArgReference_bat(stk, pci, 1) = brn->batCacheid;
1458 0 : BBPkeepref(bln);
1459 0 : BBPkeepref(brn);
1460 0 : return MAL_SUCCEED;
1461 : }
1462 :
1463 0 : if( p == NULL){
1464 0 : bl = BATdescriptor(*getArgReference_bat(stk,pci,2));
1465 0 : if( bl == NULL)
1466 0 : throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1467 : }
1468 0 : if ( q == NULL){
1469 : /* p != NULL, hence bl == NULL */
1470 0 : br = BATdescriptor(*getArgReference_bat(stk,pci,3));
1471 0 : if( br == NULL)
1472 0 : throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1473 : }
1474 :
1475 : // in case of both generators || getModuleId(q) == generatorRef)materialize the 'smallest' one first
1476 : // or implement more knowledge, postponed
1477 0 : if (p && q ){
1478 0 : msg = VLTgenerator_table_(&bl, cntxt, mb, stk, p);
1479 0 : if( msg || bl == NULL )
1480 0 : throw(MAL,"generator.join",SQLSTATE(42000) "Join over generator pairs not supported");
1481 : else
1482 : p = NULL;
1483 : materialized =1;
1484 : }
1485 :
1486 : // switch roles to have a single target bat[:oid,:any] designated
1487 : // by b and reference instruction p for the generator
1488 0 : b = q? bl : br;
1489 0 : p = q? q : p;
1490 0 : cnt = BATcount(b);
1491 0 : tpe = b->ttype;
1492 0 : o= b->hseqbase;
1493 :
1494 0 : bln = COLnew(0,TYPE_oid, cnt, TRANSIENT);
1495 0 : brn = COLnew(0,TYPE_oid, cnt, TRANSIENT);
1496 0 : if( bln == NULL || brn == NULL){
1497 0 : BBPreclaim(bln);
1498 0 : BBPreclaim(brn);
1499 0 : BBPreclaim(bl);
1500 0 : BBPreclaim(br);
1501 0 : throw(MAL,"generator.join", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1502 : }
1503 0 : ol = (oid*) Tloc(bln,0);
1504 0 : or = (oid*) Tloc(brn,0);
1505 :
1506 : /* The actual join code for generators be injected here */
1507 0 : switch(tpe){
1508 0 : case TYPE_bte: VLTjoin(bte,abs); break;
1509 0 : case TYPE_sht: VLTjoin(sht,abs); break;
1510 0 : case TYPE_int: VLTjoin(int,abs); break;
1511 0 : case TYPE_lng: VLTjoin(lng,llabs); break;
1512 : #ifdef HAVE_HGE
1513 0 : case TYPE_hge: VLTjoin(hge,HGE_ABS); break;
1514 : #endif
1515 0 : case TYPE_flt: VLTjoin(flt,fabsf); break;
1516 0 : case TYPE_dbl: VLTjoin(dbl,fabs); break;
1517 0 : default:
1518 0 : if(tpe == TYPE_date || tpe == TYPE_timestamp){
1519 : // it is easier to produce the date or timestamp series
1520 : // then to estimate the possible index
1521 0 : }
1522 0 : BBPunfix(bln->batCacheid);
1523 0 : BBPunfix(brn->batCacheid);
1524 0 : BBPreclaim(bl);
1525 0 : BBPreclaim(br);
1526 0 : throw(MAL,"generator.join", SQLSTATE(42000) "Illegal type");
1527 : }
1528 :
1529 0 : BATsetcount(bln,c);
1530 0 : bln->tsorted = bln->trevsorted = false;
1531 0 : bln->tkey = false;
1532 0 : bln->tnil = false;
1533 0 : bln->tnonil = false;
1534 0 : bln->tsorted = incr || c <= 1;
1535 0 : bln->trevsorted = !incr || c <= 1;
1536 :
1537 0 : BATsetcount(brn,c);
1538 0 : brn->tsorted = brn->trevsorted = false;
1539 0 : brn->tkey = false;
1540 0 : brn->tnil = false;
1541 0 : brn->tnonil = false;
1542 0 : brn->tsorted = incr || c <= 1;
1543 0 : brn->trevsorted = !incr || c <= 1;
1544 0 : if( q){
1545 0 : *getArgReference_bat(stk,pci,0) = brn->batCacheid;
1546 0 : BBPkeepref(brn);
1547 0 : *getArgReference_bat(stk,pci,1) = bln->batCacheid;
1548 0 : BBPkeepref(bln);
1549 : } else {
1550 0 : *getArgReference_bat(stk,pci,0) = bln->batCacheid;
1551 0 : BBPkeepref(bln);
1552 0 : *getArgReference_bat(stk,pci,1) = brn->batCacheid;
1553 0 : BBPkeepref(brn);
1554 : }
1555 0 : if ( materialized){
1556 0 : BBPreclaim(bl);
1557 0 : bl = 0;
1558 : }
1559 0 : BBPreclaim(bl);
1560 0 : BBPreclaim(br);
1561 : return msg;
1562 : }
1563 :
1564 : #define VLTrangeExpand() \
1565 : do { \
1566 : limit+= cnt * (limit/(done?done:1)+1); \
1567 : if (BATextend(bln, limit) != GDK_SUCCEED) { \
1568 : BBPunfix(blow->batCacheid); \
1569 : BBPunfix(bhgh->batCacheid); \
1570 : BBPunfix(bln->batCacheid); \
1571 : BBPunfix(brn->batCacheid); \
1572 : throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
1573 : } \
1574 : if (BATextend(brn, limit) != GDK_SUCCEED) { \
1575 : BBPunfix(blow->batCacheid); \
1576 : BBPunfix(bhgh->batCacheid); \
1577 : BBPunfix(bln->batCacheid); \
1578 : BBPunfix(brn->batCacheid); \
1579 : throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
1580 : } \
1581 : ol = (oid*) Tloc(bln,0) + c; \
1582 : or = (oid*) Tloc(brn,0) + c; \
1583 : } while (0)
1584 :
1585 : /* The operands of a join operation can either be defined on a generator */
1586 : #define VLTrangejoin(TPE, ABS, FLOOR) \
1587 : do { \
1588 : TPE f,f1,l,s; TPE *vlow,*vhgh; BUN w; \
1589 : f = *getArgReference_##TPE(stk,p, 1); \
1590 : l = *getArgReference_##TPE(stk,p, 2); \
1591 : if ( p->argc == 3) \
1592 : s = f<l? (TPE) 1: (TPE)-1; \
1593 : else \
1594 : s = * getArgReference_##TPE(stk, p, 3); \
1595 : incr = s > 0; \
1596 : if ( s == 0 || (f> l && s>0) || (f<l && s < 0)) { \
1597 : BBPreclaim(bln); \
1598 : BBPreclaim(brn); \
1599 : BBPreclaim(blow); \
1600 : BBPreclaim(bhgh); \
1601 : throw(MAL,"generator.rangejoin", SQLSTATE(42000) "Illegal range"); \
1602 : } \
1603 : vlow = (TPE*) Tloc(blow,0); \
1604 : vhgh = (TPE*) Tloc(bhgh,0); \
1605 : for( ; cnt >0; cnt--, done++, o++,vlow++,vhgh++){ \
1606 : f1 = f + FLOOR(ABS(*vlow-f)/ABS(s)) * s; \
1607 : if ( f1 < *vlow ) \
1608 : f1+= s; \
1609 : w = (BUN) FLOOR(ABS(f1-f)/ABS(s)); \
1610 : for( ; (f1 > *vlow || (li && f1 == *vlow)) && (f1 < *vhgh || (ri && f1 == *vhgh)); f1 += s, w++){ \
1611 : if(c == limit) \
1612 : VLTrangeExpand(); \
1613 : *ol++ = (oid) w; \
1614 : *or++ = o; \
1615 : c++; \
1616 : } \
1617 : } \
1618 : } while (0)
1619 :
1620 0 : str VLTgenerator_rangejoin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1621 : {
1622 0 : BAT *blow = NULL, *bhgh = NULL, *bln = NULL, *brn= NULL;
1623 0 : bit li,ri;
1624 0 : BUN limit, cnt, done=0, c =0;
1625 0 : oid o= 0, *ol, *or;
1626 0 : int tpe, incr=0;
1627 0 : InstrPtr p = NULL;
1628 0 : str msg = MAL_SUCCEED;
1629 :
1630 0 : (void) cntxt;
1631 : // the left join argument should be a generator
1632 0 : p = findGeneratorDefinition(mb,pci,pci->argv[2]);
1633 0 : if( p == NULL)
1634 0 : throw(MAL,"generator.rangejoin",SQLSTATE(42000) "Invalid arguments");
1635 :
1636 0 : blow = BATdescriptor(*getArgReference_bat(stk,pci,3));
1637 0 : if( blow == NULL)
1638 0 : throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1639 :
1640 0 : bhgh = BATdescriptor(*getArgReference_bat(stk,pci,4));
1641 0 : if( bhgh == NULL){
1642 0 : BBPunfix(blow->batCacheid);
1643 0 : throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1644 : }
1645 0 : li = *getArgReference_bit(stk,pci,5);
1646 0 : ri = *getArgReference_bit(stk,pci,6);
1647 :
1648 0 : cnt = BATcount(blow);
1649 0 : limit = 2 * cnt; //top off result before expansion
1650 0 : tpe = blow->ttype;
1651 0 : o= blow->hseqbase;
1652 :
1653 0 : bln = COLnew(0,TYPE_oid, limit, TRANSIENT);
1654 0 : brn = COLnew(0,TYPE_oid, limit, TRANSIENT);
1655 0 : if( bln == NULL || brn == NULL){
1656 0 : BBPreclaim(bln);
1657 0 : BBPreclaim(brn);
1658 0 : BBPreclaim(blow);
1659 0 : BBPreclaim(bhgh);
1660 0 : throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1661 : }
1662 0 : ol = (oid*) Tloc(bln,0);
1663 0 : or = (oid*) Tloc(brn,0);
1664 :
1665 : /* The actual join code for generators be injected here */
1666 0 : switch(tpe){
1667 0 : case TYPE_bte: VLTrangejoin(bte,abs,IDENTITY); break;
1668 0 : case TYPE_sht: VLTrangejoin(sht,abs,IDENTITY); break;
1669 0 : case TYPE_int: VLTrangejoin(int,abs,IDENTITY); break;
1670 0 : case TYPE_lng: VLTrangejoin(lng,llabs,IDENTITY); break;
1671 : #ifdef HAVE_HGE
1672 0 : case TYPE_hge: VLTrangejoin(hge,HGE_ABS,IDENTITY); break;
1673 : #endif
1674 0 : case TYPE_flt: VLTrangejoin(flt,fabsf,floorf); break;
1675 0 : case TYPE_dbl: VLTrangejoin(dbl,fabs,floor); break;
1676 0 : default:
1677 0 : if( tpe == TYPE_date || tpe == TYPE_timestamp){
1678 : // it is easier to produce the date or timestamp series
1679 : // then to estimate the possible index
1680 0 : }
1681 0 : BBPreclaim(bln);
1682 0 : BBPreclaim(brn);
1683 0 : BBPreclaim(blow);
1684 0 : BBPreclaim(bhgh);
1685 0 : throw(MAL,"generator.rangejoin","Illegal type");
1686 : }
1687 :
1688 0 : BATsetcount(bln,c);
1689 0 : bln->tsorted = bln->trevsorted = false;
1690 0 : bln->tkey = false;
1691 0 : bln->tnil = false;
1692 0 : bln->tnonil = false;
1693 0 : bln->tsorted = incr || c <= 1;
1694 0 : bln->trevsorted = !incr || c <= 1;
1695 :
1696 0 : BATsetcount(brn,c);
1697 0 : brn->tsorted = brn->trevsorted = false;
1698 0 : brn->tkey = false;
1699 0 : brn->tnil = false;
1700 0 : brn->tnonil = false;
1701 0 : brn->tsorted = incr || c <= 1;
1702 0 : brn->trevsorted = !incr || c <= 1;
1703 0 : *getArgReference_bat(stk,pci,0) = bln->batCacheid;
1704 0 : BBPkeepref(bln);
1705 0 : *getArgReference_bat(stk,pci,1) = brn->batCacheid;
1706 0 : BBPkeepref(brn);
1707 0 : BBPreclaim(blow);
1708 0 : BBPreclaim(bhgh);
1709 0 : return msg;
1710 : }
1711 :
1712 : #include "mel.h"
1713 : static mel_func generator_init_funcs[] = {
1714 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
1715 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
1716 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
1717 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
1718 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
1719 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
1720 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
1721 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
1722 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
1723 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
1724 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
1725 : 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))),
1726 : pattern("generator", "series", VLTgenerator_table, false, "date generator with step size in months", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",int))),
1727 : pattern("generator", "series", VLTgenerator_table, false, "date generator with step size in days", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",lng))),
1728 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",timestamp),arg("first",timestamp),arg("limit",timestamp),arg("step",lng))),
1729 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
1730 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
1731 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
1732 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
1733 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
1734 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",dbl),arg("first",dbl),arg("limit",dbl),arg("step",dbl))),
1735 : pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize (months)", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",int))),
1736 : pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize (days)", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",lng))),
1737 : 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))),
1738 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
1739 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
1740 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
1741 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
1742 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
1743 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
1744 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",bte),batarg("cnd",oid),arg("low",bte),arg("oper",str))),
1745 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",sht),batarg("cnd",oid),arg("low",sht),arg("oper",str))),
1746 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",int),batarg("cnd",oid),arg("low",int),arg("oper",str))),
1747 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",lng),batarg("cnd",oid),arg("low",lng),arg("oper",str))),
1748 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",flt),batarg("cnd",oid),arg("low",flt),arg("oper",str))),
1749 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",dbl),batarg("cnd",oid),arg("low",dbl),arg("oper",str))),
1750 : pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "Overloaded selection routine", args(1,5, batarg("",oid),batarg("b",date),batarg("cnd",oid),arg("low",date),arg("oper",str))),
1751 : 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))),
1752 : 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))),
1753 : 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))),
1754 : 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))),
1755 : 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))),
1756 : 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))),
1757 : 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))),
1758 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",date),arg("low",date),arg("high",date),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1759 : 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))),
1760 : 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))),
1761 : 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))),
1762 : 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))),
1763 : 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))),
1764 : 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))),
1765 : 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))),
1766 : pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",date),batarg("cand",oid),arg("low",date),arg("high",date),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1767 : 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))),
1768 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",bte),batarg("b",oid),batarg("cand",bte))),
1769 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",sht),batarg("b",oid),batarg("cand",sht))),
1770 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",int),batarg("b",oid),batarg("cand",int))),
1771 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",lng),batarg("b",oid),batarg("cand",lng))),
1772 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",flt),batarg("b",oid),batarg("cand",flt))),
1773 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",dbl),batarg("b",oid),batarg("cand",dbl))),
1774 : pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",date),batarg("b",oid),batarg("cand",date))),
1775 : pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",timestamp),batarg("b",oid),batarg("cand",timestamp))),
1776 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",bte),batarg("gen",bte))),
1777 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",sht),batarg("gen",sht))),
1778 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",int),batarg("gen",int))),
1779 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",lng),batarg("gen",lng))),
1780 : pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",flt),batarg("gen",flt))),
1781 : pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",dbl),batarg("gen",dbl))),
1782 : 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))),
1783 : 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))),
1784 : 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))),
1785 : 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))),
1786 : 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))),
1787 : 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))),
1788 : #ifdef HAVE_HGE
1789 : pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
1790 : 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))),
1791 : 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))),
1792 : pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
1793 : 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))),
1794 : 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))),
1795 : 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))),
1796 : pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",hge),batarg("b",oid),batarg("cand",hge))),
1797 : pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",hge),batarg("gen",hge))),
1798 : #endif
1799 : { .imp=NULL }
1800 : };
1801 : #include "mal_import.h"
1802 : #ifdef _MSC_VER
1803 : #undef read
1804 : #pragma section(".CRT$XCU",read)
1805 : #endif
1806 315 : LIB_STARTUP_FUNC(init_generator_mal)
1807 315 : { mal_module("generator", NULL, generator_init_funcs); }
|