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 
16 #include <config.h>
17 #include	<nnconfig.h>
18 #include	<yystmt.h>
19 #include	<yylex.h>
20 #include	<nncol.h>
21 #include	<nndate.h>
22 #include	<yyerr.h>
23 
getleaftype(yystmt_t * yystmt,node_t * nd)24 static int	getleaftype(yystmt_t* yystmt, node_t* nd)
25 {
26 	yypar_t*	par;
27 	yyattr_t*	attr;
28 
29 	switch( nd->type )
30 	{
31 		case en_nt_attr:
32 			attr = yystmt->pattr + (nd->value).iattr;
33 
34 			switch((nd->value).iattr)
35 			{
36 				case en_lines:
37 				case en_article_num:
38 				case en_sql_num:
39 				case en_sql_count:
40 					return en_nt_num;
41 
42 				case en_date:
43 				case en_sql_date:
44 					return en_nt_date;
45 
46 				default:
47 					break;
48 			}
49 			return en_nt_qstr;
50 
51 		case en_nt_param:
52 			par = yystmt->ppar + (nd->value).ipar - 1;
53 
54 			switch(par->type)
55 			{
56 				case en_nt_null:
57 				case en_nt_num:
58 				case en_nt_qstr:
59 				case en_nt_date:
60 					break;
61 
62 				default:
63 					return -1;
64 			}
65 			return par->type;
66 
67 		case en_nt_num:
68 		case en_nt_qstr:
69 		case en_nt_date:
70 		case en_nt_null:
71 			return nd->type;
72 
73 		default:
74 			return -1;
75 	}
76 }
77 
cmp_tchk(yystmt_t * yystmt,node_t * a,node_t * b)78 static int	cmp_tchk(yystmt_t* yystmt, node_t* a, node_t* b)
79 {
80 	int	ta, tb;
81 
82 	ta = getleaftype( yystmt, a );
83 	tb = getleaftype( yystmt, b );
84 
85 	if( ta == -1 || tb == -1 )
86 		return -1;
87 
88 	if( ta == en_nt_date && tb == en_nt_qstr )
89 		return 0;
90 
91 	if( ta != tb && ta != en_nt_null && tb != en_nt_null )
92 		return -1;
93 
94 	return 0;
95 }
96 
evl_like_tchk(yystmt_t * yystmt,node_t * a,node_t * b)97 static	int	evl_like_tchk(yystmt_t* yystmt, node_t* a, node_t* b)
98 {
99 	int	ta, tb;
100 
101 	ta = getleaftype(yystmt, a);
102 	tb = getleaftype(yystmt, b);
103 
104 	if( tb == en_nt_null
105 	 || tb == en_nt_null )
106 		return 0;
107 
108 	if( ta != en_nt_qstr
109 	 || tb != en_nt_qstr )
110 		return -1;
111 
112 	return 0;
113 }
114 
srchtree_tchk(yystmt_t * yystmt,node_t * node)115 static int srchtree_tchk(yystmt_t* yystmt, node_t* node)
116 /* return -1: err or syserr, 0: ok */
117 {
118 	int	r, s, flag = 0;
119 	node_t* ptr;
120 
121 	if( ! node )
122 		return 0;
123 
124 	switch( node->type )
125 	{
126 		case en_nt_cmpop:
127 			return cmp_tchk(yystmt, node->left, node->right);
128 
129 		case en_nt_logop:
130 			switch( (node->value).logop )
131 			{
132 				case en_logop_not:
133 					return srchtree_tchk(yystmt, node->right);
134 
135 				case en_logop_and:
136 				case en_logop_or:
137 					r = srchtree_tchk(yystmt, node->left);
138 					s = srchtree_tchk(yystmt, node->right);
139 
140 					if( r == -1 || s == -1 )
141 						return -1;
142 
143 					return 0;
144 
145 				default:
146 					abort();
147 					break;	/* just  for turn off the warning */
148 			}
149 			break;	/* just for turn off the warning */
150 
151 		case en_nt_isnull:
152 			return 0;
153 
154 		case en_nt_between:
155 			r = cmp_tchk(yystmt, node->left, node->right->left);
156 			s = cmp_tchk(yystmt, node->left, node->right->right);
157 
158 			if( r == -1 || s == -1 )
159 				return -1;
160 
161 			return 0;
162 
163 		case en_nt_in:
164 			for(ptr=node->right; ptr; ptr=ptr->right)
165 			{
166 				r = cmp_tchk(yystmt, node->left, ptr);
167 
168 				if( r == -1 )
169 					return -1;
170 			}
171 			return 0;
172 
173 		case en_nt_caselike:
174 		case en_nt_like:
175 			return evl_like_tchk( yystmt, node->left, node->right);
176 
177 		default:
178 			abort();
179 			break;	/* turn off the warning */
180 	}
181 
182 	return -1;	/* just for turn off the warning */
183 }
184 
nnsql_srchtree_tchk(void * hstmt)185 int	nnsql_srchtree_tchk(void* hstmt)
186 {
187 	yystmt_t*	yystmt = hstmt;
188 	int		r;
189 
190 	r = srchtree_tchk(yystmt, yystmt->srchtree);
191 
192 	if( r )
193 		yystmt->errcode = TYPE_VIOLATION;
194 
195 	return r;
196 }
197