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