1 /**
2 Copyright (C) 1995, 1996 by Ke Jin <kejin@visigenic.com>
3 Enhanced for unixODBC (1999) by Peter Harvey <pharvey@codebydesign.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 **/
15 #include <config.h>
16 #include <nnconfig.h>
17 #include <yystmt.h>
18 #include <yylex.h>
19 #include <nncol.h>
20 #include <nndate.h>
21
22 typedef struct {
23 int type; /* can only be en_nt_qstr, en_nt_num and en_nt_null */
24
25 union {
26 char* qstr;
27 long num;
28 date_t date;
29 } value;
30 } leaf_t;
31
getleaf(yystmt_t * yystmt,node_t * nd,leaf_t * lf)32 static int getleaf(yystmt_t* yystmt, node_t* nd, leaf_t* lf)
33 {
34 yypar_t* par;
35 yyattr_t* attr;
36
37 switch( nd->type )
38 {
39 case en_nt_attr:
40 attr = yystmt->pattr + (nd->value).iattr;
41
42 if( (nd->value).iattr == en_lines
43 || (nd->value).iattr == en_article_num )
44 {
45 lf->type = en_nt_num;
46 (lf->value).num = (attr->value).number;
47 break;
48 }
49
50 if( (nd->value).iattr == en_date )
51 {
52 if( (attr->value).date.day )
53 {
54 lf->type = en_nt_date;
55 (lf->value).date =
56 (attr->value).date;
57 }
58 else
59 lf->type = en_nt_null;
60 break;
61 }
62
63 if( (attr->value).location )
64 {
65 lf->type = en_nt_qstr;
66 (lf->value).qstr =
67 (attr->value).location;
68 }
69 else
70 lf->type = en_nt_null;
71 break;
72
73 case en_nt_param:
74 par = yystmt->ppar + (nd->value).ipar - 1;
75
76 if( par->type == en_nt_null )
77 {
78 lf->type = en_nt_null;
79 break;
80 }
81
82 if( par->type == en_nt_num )
83 {
84 lf->type = en_nt_num;
85 (lf->value).num = (par->value).number;
86 break;
87 }
88
89 if( par->type == en_nt_qstr)
90 {
91 if( (par->value).location )
92 {
93 lf->type = en_nt_qstr;
94
95 (lf->value).qstr =
96 (par->value).location;
97 break;
98 }
99
100 lf->type = en_nt_null;
101 break;
102 }
103
104 if( par->type == en_nt_date)
105 {
106 if( (par->value).date.day )
107 {
108 lf->type = en_nt_date;
109
110 (lf->value).date =
111 (par->value).date;
112 break;
113 }
114
115 lf->type = en_nt_null;
116 }
117
118 return -1;
119
120 case en_nt_num:
121 lf->type = en_nt_num;
122 (lf->value).num = (nd->value).num;
123 break;
124
125 case en_nt_qstr:
126 lf->type = en_nt_qstr;
127
128 if( (nd->value).qstr )
129 {
130 lf->type = en_nt_qstr;
131 (lf->value).qstr = (nd->value).qstr;
132 break;
133 }
134
135 lf->type = en_nt_null;
136 break;
137
138 case en_nt_date:
139 lf->type = en_nt_date;
140
141 (lf->value).date = (nd->value).date;
142 break;
143
144 case en_nt_null:
145 lf->type = en_nt_null;
146 break;
147
148 default:
149 return -1;
150 }
151
152 return 0;
153 }
154
155 #ifndef MAX_SIGNED_LONG
156 # define MAX_SIGNED_LONG ((-1UL) >> 1)
157 #endif
158
159 # define AREA ( MAX_SIGNED_LONG + 1UL )
160 # define RANGE_ALL { 0, 1UL, MAX_SIGNED_LONG }
161 # define RANGE_EMPTY { 1, 0UL, 0UL }
162 # define ALL_RANGE(r) { r.flag = 0; \
163 r.min = 1UL; \
164 r.max = MAX_SIGNED_LONG; }
165 # define EMPTY_RANGE(r) { r.flag = 1;\
166 r.min = r.max = 0UL; }
167 # define IS_EMPTY_RANGE(r) \
168 (((r.min == 0UL) && (r.max==0UL))? 1:0)
169 # define RANGE_MIN(a, b) ((((unsigned long)(a)) < ((unsigned long)(b)))? a:b)
170 # define RANGE_MAX(a, b) ((((unsigned long)(a)) > ((unsigned long)(b)))? a:b)
171
172 typedef struct {
173 int flag;
174 unsigned long min;
175 unsigned long max;
176 } range_t;
177
range_and(range_t r1,range_t r2)178 static range_t range_and(range_t r1, range_t r2)
179 {
180 range_t r = RANGE_EMPTY;
181
182 if( !(r.flag = r1.flag || r2.flag) )
183 return r;
184
185 if( r1.min > r2.max
186 || r1.max < r2.min )
187 return r;
188
189 r.min = (RANGE_MAX(r1.min, r2.min))%AREA;
190 r.max = (RANGE_MIN(r1.max, r2.max))%AREA;
191
192 return r;
193 }
194
range_or(range_t r1,range_t r2)195 static range_t range_or(range_t r1, range_t r2)
196 {
197 range_t r = RANGE_ALL;
198
199 if( !(r.flag = r1.flag || r2.flag) )
200 return r;
201
202 if( !(r1.max/AREA) || !(r2.max/AREA) )
203 /* at least one of the rangion does not cross cell */
204 {
205 unsigned long c1, c2;
206
207 c1 = (r1.max/2) + (r1.min/2); /* central of rangion 1 */
208 c2 = (r2.max/2) + (r2.min/2); /* central of rangion 2 */
209
210 if( c1 > c2 && (c1 - c2) > (AREA/2) )
211 {
212 /* shift it to the second cell */
213 r2.min += AREA;
214 r2.max += AREA;
215 }
216 else
217 if( c2 > c1 && (c2 - c1) > (AREA/2) )
218 {
219 /* shift it to the second cell */
220 r1.min += AREA;
221 r1.max += AREA;
222 }
223 }
224
225 r.min = (RANGE_MIN(r1.min, r2.min))%AREA;
226 r.max = (RANGE_MAX(r1.max, r2.max))%AREA;
227
228 return r;
229 }
230
getrange(yystmt_t * yystmt,node_t * pnd)231 static range_t getrange(yystmt_t* yystmt, node_t* pnd)
232 {
233 range_t r = RANGE_ALL, r1, r2;
234 node_t* tpnd = 0;
235 leaf_t a, b;
236 int flag = 0;
237
238 if( !pnd )
239 return r;
240
241 if( pnd->left
242 && pnd->left->type == en_nt_attr
243 && (pnd->left->value).iattr == en_article_num )
244 {
245 r.flag = 1;
246
247 switch( pnd->type )
248 {
249 case en_nt_between:
250 getleaf(yystmt, pnd->right->left, &a);
251 getleaf(yystmt, pnd->right->right, &b);
252
253 if( a.type == en_nt_null
254 || b.type == en_nt_null )
255 break;
256
257 r.min = RANGE_MIN(a.value.num, b.value.num);
258 r.max = RANGE_MAX(a.value.num, b.value.num);
259 break;
260
261 case en_nt_in:
262 EMPTY_RANGE(r);
263
264 for(tpnd = pnd->right; tpnd; tpnd=tpnd->right)
265 {
266 getleaf(yystmt, tpnd, &a);
267
268 if( a.type == en_nt_null )
269 continue;
270
271 if( IS_EMPTY_RANGE(r) )
272 r.min = r.max = a.value.num;
273 else
274 {
275 r.min = RANGE_MIN(r.min, a.value.num);
276 r.max = RANGE_MAX(r.max, a.value.num);
277 }
278 }
279 break;
280
281 case en_nt_cmpop:
282 getleaf(yystmt, pnd->right, &a);
283
284 if( a.type == en_nt_null )
285 break;
286
287 switch((pnd->value).cmpop)
288 {
289 case en_cmpop_eq:
290 r.min = r.max = a.value.num;
291 break;
292
293 case en_cmpop_ne:
294 r.min = (a.value.num + 1UL )%AREA;
295 r.max = (a.value.num - 1UL + AREA)%AREA;
296 break;
297
298 case en_cmpop_gt:
299 r.min = (a.value.num + 1UL)%AREA;
300 break;
301
302 case en_cmpop_lt:
303 r.max = (a.value.num - 1UL + AREA)%AREA;
304 r.min = (r.max)? 1UL:0UL;
305 break;
306
307 case en_cmpop_ge:
308 r.min = a.value.num;
309 break;
310
311 case en_cmpop_le:
312 r.max = a.value.num;
313 r.min = (r.max)? 1UL:0UL;
314 break;
315
316 default:
317 EMPTY_RANGE(r);
318 break;
319 }
320 break;
321
322 default:
323 break;
324 }
325
326 return r;
327 }
328
329 if( pnd->type != en_nt_logop )
330 return r;
331
332 switch( (pnd->value).logop )
333 {
334 case en_logop_not:
335 r1 = getrange(yystmt, pnd->right);
336 if( r1.flag )
337 {
338 r.min = (r1.max + 1UL)%AREA;
339 r.max = (r1.min - 1UL + AREA)%AREA;
340 }
341 break;
342
343 case en_logop_or:
344 flag = 1;
345 case en_logop_and:
346 r1 = getrange(yystmt, pnd->left);
347 r2 = getrange(yystmt, pnd->right);
348
349 if( !(r1.flag || r2.flag ) )
350 break;
351
352 if( r1.min > r1.max )
353 r1.max = r1.max + AREA;
354
355 if( r2.min > r2.max )
356 r2.max = r2.max + AREA;
357
358 if( flag )
359 r = range_or ( r1, r2 );
360 else
361 r = range_and( r1, r2 );
362 break;
363
364 default:
365 EMPTY_RANGE(r);
366 break;
367 }
368
369 return r;
370 }
371
nnsql_getrange(void * hstmt,long * pmin,long * pmax)372 void nnsql_getrange(void* hstmt, long* pmin, long* pmax)
373 {
374 yystmt_t* yystmt = hstmt;
375 range_t r;
376
377 r = getrange(hstmt, yystmt->srchtree);
378
379 if( !r.flag )
380 {
381 *pmin = 1UL;
382 *pmax = MAX_SIGNED_LONG;
383 }
384 else
385 {
386 *pmin = r.min;
387 *pmax = r.max;
388 }
389 }
390
is_sql_null(yystmt_t * yystmt,node_t * a)391 static int is_sql_null(yystmt_t* yystmt, node_t* a)
392 {
393 leaf_t lf;
394
395 if( getleaf(yystmt, a, &lf) )
396 return -1;
397
398 return (lf.type == en_nt_null);
399 }
400
compare(yystmt_t * yystmt,node_t * a,node_t * b,int op)401 static int compare(yystmt_t* yystmt, node_t* a, node_t* b, int op)
402 {
403 leaf_t la, lb;
404 int diff, r;
405
406 if( getleaf( yystmt, a, &la )
407 || getleaf( yystmt, b, &lb ) )
408 return -1;
409
410 if( la.type == en_nt_date && lb.type == en_nt_qstr )
411 {
412 lb.type = en_nt_date;
413
414 if( nnsql_odbcdatestr2date(lb.value.qstr, &(lb.value.date)) )
415 return -1;
416 }
417
418 if( la.type != lb.type
419 || la.type == en_nt_null
420 || lb.type == en_nt_null )
421 return 0;
422
423 switch( la.type )
424 {
425 case en_nt_qstr:
426 diff = STRCMP(la.value.qstr, lb.value.qstr);
427 break;
428
429 case en_nt_num:
430 diff = la.value.num - lb.value.num;
431 break;
432
433 case en_nt_date:
434 diff = nnsql_datecmp(&(la.value.date), &(lb.value.date));
435 break;
436
437 default:
438 abort();
439 return -1;
440 }
441
442 switch(op)
443 {
444 case en_cmpop_eq:
445 r = !diff;
446 break;
447
448 case en_cmpop_ne:
449 r = !!diff;
450 break;
451
452 case en_cmpop_gt:
453 r = (diff>0)? 1:0;
454 break;
455
456 case en_cmpop_ge:
457 r = (diff>=0)? 1:0;
458 break;
459
460 case en_cmpop_lt:
461 r = (diff<0)? 1:0;
462 break;
463
464 case en_cmpop_le:
465 r = (diff<=0)? 1:0;
466 break;
467
468 default:
469 r = -1;
470 break;
471 }
472
473 return r;
474 }
475
ch_case_cmp(char a,char b)476 static int ch_case_cmp(char a, char b)
477 {
478 if( a >= 'a' && a <= 'z' )
479 a += ('A' - 'a');
480
481 if( b >= 'a' && b <= 'z' )
482 b += ('A' - 'a');
483
484 return (a - b);
485 }
486
strlike(char * str,char * pattern,char esc,int flag)487 static int strlike(
488 char* str,
489 char* pattern,
490 char esc,
491 int flag ) /* flag = 0: case sensitive */
492 {
493 char c, cp;
494
495 for(;;str++, pattern++)
496 {
497 c = *str;
498 cp= *pattern;
499
500 if( esc && cp == esc )
501 {
502 cp = *pattern++;
503
504 if( (!flag && (c - cp) )
505 || ( flag && ch_case_cmp(c, cp) ) )
506 return 0;
507
508 if( !c )
509 return 1;
510
511 continue;
512 }
513
514 switch(cp)
515 {
516 case 0:
517 return !c;
518
519 case '_':
520 if(!c)
521 return 0;
522 break;
523
524 case '%':
525 if(! *(pattern + 1) )
526 return 1;
527
528 for(;*str;str++)
529 {
530 if(strlike(str,
531 pattern + 1, esc, flag))
532 return 1;
533 }
534 return 0;
535
536 default:
537 if( (!flag && (c - cp) )
538 || ( flag && ch_case_cmp(c, cp) ) )
539 return 0;
540 break;
541 }
542 }
543 }
544
nnsql_strlike(char * str,char * pattern,char esc,int flag)545 int nnsql_strlike(char* str, char* pattern, char esc, int flag)
546 {
547 return strlike(str, pattern, esc, flag);
548 }
549
evl_like(yystmt_t * yystmt,node_t * a,node_t * b,char esc,int flag)550 static int evl_like(yystmt_t* yystmt, node_t* a, node_t* b, char esc, int flag)
551 {
552 leaf_t la, lb;
553
554 if( getleaf(yystmt, a, &la )
555 || getleaf(yystmt, b, &lb ) )
556 return -1;
557
558 if( la.type != en_nt_qstr
559 || lb.type != en_nt_qstr )
560 return 0;
561
562 return strlike(la.value.qstr, lb.value.qstr, esc, flag);
563 }
564
srchtree_evl(yystmt_t * yystmt,node_t * node)565 static int srchtree_evl(yystmt_t* yystmt, node_t* node)
566 /* return -1: syserr, 0: fail, 1: true */
567 {
568 int r, s, flag = 0;
569 node_t* ptr;
570
571 if( ! node )
572 return 1;
573
574 switch( node->type )
575 {
576 case en_nt_cmpop:
577 return compare(yystmt, node->left, node->right,
578 (node->value).cmpop);
579
580 case en_nt_logop:
581 switch( (node->value).logop )
582 {
583 case en_logop_not:
584 r = srchtree_evl(yystmt, node->right);
585 if( r == -1 )
586 return -1;
587 return ( ! r );
588
589 case en_logop_and:
590 flag = 1;
591 case en_logop_or:
592 r = srchtree_evl(yystmt, node->left);
593 s = srchtree_evl(yystmt, node->right);
594
595 if( r == -1 || s == -1 )
596 return -1;
597
598 if( flag )
599 return ( r && s );
600 else
601 return ( r || s );
602
603 default:
604 abort();
605 break; /* just for turn off the warning */
606 }
607 break; /* just for turn off the warning */
608
609 case en_nt_isnull:
610 return is_sql_null(yystmt, node->left);
611
612 case en_nt_between:
613 r = compare(yystmt, node->left, node->right->left, en_cmpop_ge);
614 s = compare(yystmt, node->left, node->right->right, en_cmpop_le);
615
616 if( r == -1 || s == -1 )
617 return -1;
618
619 return ( r && s );
620
621 case en_nt_in:
622 for(ptr=node->right; ptr; ptr=ptr->right)
623 {
624 r = compare(yystmt, node->left, ptr, en_cmpop_eq);
625
626 if( r ) /* -1 or 1 */
627 return r;
628 }
629 return 0;
630
631 case en_nt_caselike:
632 flag = 1;
633 case en_nt_like:
634 return evl_like( yystmt, node->left, node->right,
635 (node->value).esc, flag );
636
637 default:
638 abort();
639 break; /* turn off the warning */
640 }
641
642 return -1; /* just for turn off the warning */
643 }
644
nnsql_srchtree_evl(void * hstmt)645 int nnsql_srchtree_evl(void* hstmt)
646 {
647 yystmt_t* yystmt = hstmt;
648
649 return srchtree_evl(yystmt, yystmt->srchtree);
650 }
651