1 
2 /*****************************************************************************
3 *
4 * MODULE:       SQL statement parser library
5 *
6 * AUTHOR(S):    lex.l and yac.y were originally taken from unixODBC and
7 *               probably written by Peter Harvey <pharvey@codebydesigns.com>,
8 *               original modifications & added code by
9 *                     Radim Blazek <radim.blazek gmail.com>
10 *               Glynn Clements <glynn gclements.plus.com>,
11 *               Markus Neteler <neteler itc.it>,
12 *               Martin Landa <landa.martin gmail.com>,
13 *               Moritz Lennert <mlennert club.worldonline.be>,
14 *               Hamish Bowman <hamish_b yahoo.com>,
15 *               Daniel Calvelo Aros <dca.gis gmail.com>,
16 *               Paul Kelly <paul-grass stjohnspoint.co.uk>,
17 *               Alex Shevlakov <sixote yahoo.com>
18 *
19 * PURPOSE:      Parse input string containing SQL statement to
20 *               SQLPSTMT structure.
21 *               SQL parser may be used by simple database drivers.
22 *
23 * COPYRIGHT:    (C) 2000-2007 by the GRASS Development Team
24 *
25 *               This program is free software under the GNU General Public
26 *   	    	License (>=v2). Read the file COPYING that comes with GRASS
27 *   	    	for details.
28 *
29 *****************************************************************************/
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <assert.h>
36 #include <grass/sqlp.h>
37 
38 SQLPSTMT *sqlpStmt;
39 
40 /* save string to value */
sqpSaveStr(SQLPVALUE * val,char * c)41 int sqpSaveStr(SQLPVALUE * val, char *c)
42 {
43     int len = 0;
44 
45     len = strlen(c) + 1;
46     val->s = (char *)realloc(val->s, len);
47 
48     strcpy(val->s, c);
49 
50     return (1);
51 }
52 
sqpInitValue(SQLPVALUE * val)53 void sqpInitValue(SQLPVALUE * val)
54 {
55     val->type = SQLP_NULL;
56     val->s = NULL;
57     val->i = 0;
58     val->d = 0.0;
59 }
60 
sqpCopyValue(SQLPVALUE * from,SQLPVALUE * to)61 void sqpCopyValue(SQLPVALUE * from, SQLPVALUE * to)
62 {
63     to->type = from->type;
64 
65     if (to->s)
66 	free(to->s);
67 
68     if (from->s)
69 	to->s = strdup(from->s);
70 
71     to->i = from->i;
72     to->d = from->d;
73 }
74 
sqpInitParser(SQLPSTMT * st)75 int sqpInitParser(SQLPSTMT * st)
76 {
77     sqlpStmt = st;
78     sqlpStmt->cur = sqlpStmt->stmt;
79 
80     sqlpStmt->errmsg[0] = '\0';
81     sqlpStmt->table[0] = '\0';
82     sqlpStmt->nCol = 0;
83     sqlpStmt->nVal = 0;
84     sqlpStmt->upperNodeptr = NULL;
85     sqlpStmt->orderCol = NULL;
86 
87     return (1);
88 }
89 
sqpCommand(int command)90 void sqpCommand(int command)
91 {
92     sqlpStmt->command = command;
93     return;
94 }
95 
sqpTable(char * tbl)96 void sqpTable(char *tbl)
97 {
98     strncpy(sqlpStmt->table, tbl, SQLP_MAX_TABLE);
99     return;
100 }
101 
sqpColumn(char * col)102 void sqpColumn(char *col)
103 {
104     int i;
105 
106     i = sqlpStmt->nCol;
107     sqpAllocCol(sqlpStmt, i + 1);
108     sqpSaveStr(&(sqlpStmt->Col[i]), col);
109 
110     sqlpStmt->nCol++;
111     return;
112 }
113 
sqpColumnDef(char * col,int type,int width,int decimals)114 void sqpColumnDef(char *col, int type, int width, int decimals)
115 {
116     int i;
117 
118     i = sqlpStmt->nCol;
119     sqpAllocCol(sqlpStmt, i + 1);
120     sqpSaveStr(&(sqlpStmt->Col[i]), col);
121     sqlpStmt->ColType[i] = type;
122     sqlpStmt->ColWidth[i] = width;
123     sqlpStmt->ColDecim[i] = decimals;
124 
125     sqlpStmt->nCol++;
126     return;
127 }
128 
sqpValue(char * strval,int intval,double dblval,int type)129 void sqpValue(char *strval, int intval, double dblval, int type)
130 {
131     int i;
132 
133     i = sqlpStmt->nVal;
134 
135     /* allocate space for cols because if in INSERT cols were not
136      * specified array for ColNum would not be allocated */
137     sqpAllocCol(sqlpStmt, i + 1);
138 
139     sqpAllocVal(sqlpStmt, i + 1);
140     sqlpStmt->Val[i].s = NULL;
141     sqlpStmt->Val[i].i = 0;	/* not necessay I think */
142     sqlpStmt->Val[i].d = 0.0;	/* not necessay I think */
143 
144     sqlpStmt->Val[i].type = type;
145     switch (type) {
146     case (SQLP_S):
147 	sqpSaveStr(&(sqlpStmt->Val[i]), strval);
148 	break;
149     case (SQLP_I):
150 	sqlpStmt->Val[i].i = intval;
151 	break;
152     case (SQLP_D):
153 	sqlpStmt->Val[i].d = dblval;
154 	break;
155 	/* SQLP_NULL, nothing to do */
156     }
157 
158     sqlpStmt->nVal++;
159     return;
160 }
161 
sqpAssignment(char * col,char * strval,int intval,double dblval,SQLPNODE * expval,int type)162 void sqpAssignment(char *col, char *strval, int intval, double dblval,
163 		   SQLPNODE * expval, int type)
164 {
165     int i;
166 
167     i = sqlpStmt->nCol;
168 
169     sqpAllocCol(sqlpStmt, i + 1);
170     sqpSaveStr(&(sqlpStmt->Col[i]), col);
171 
172     sqpAllocVal(sqlpStmt, i + 1);
173     sqlpStmt->Val[i].s = NULL;
174     sqlpStmt->Val[i].i = 0;	/* not necessay I think */
175     sqlpStmt->Val[i].d = 0.0;	/* not necessay I think */
176 
177     sqlpStmt->Val[i].type = type;
178     switch (type) {
179     case (SQLP_S):
180 	sqpSaveStr(&(sqlpStmt->Val[i]), strval);
181 	break;
182     case (SQLP_I):
183 	sqlpStmt->Val[i].i = intval;
184 	break;
185     case (SQLP_D):
186 	sqlpStmt->Val[i].d = dblval;
187 	break;
188     case (SQLP_EXPR):
189 	sqlpStmt->Val[i].expr = expval;
190 	/* Don't do anything right now; come back to this when executing */
191 	break;
192 	/* SQLP_NULL, nothing to do */
193     }
194 
195     sqlpStmt->nCol++;
196     sqlpStmt->nVal++;
197     return;
198 }
199 
sqpOrderColumn(char * col,int dir)200 void sqpOrderColumn(char *col, int dir)
201 {
202     sqlpStmt->orderCol = (char *)realloc(sqlpStmt->orderCol, strlen(col) + 1);
203     strcpy(sqlpStmt->orderCol, col);
204     sqlpStmt->orderDir = dir;
205     return;
206 }
207 
208 /* Create and init new node */
sqpNewNode(void)209 SQLPNODE *sqpNewNode(void)
210 {
211     SQLPNODE *np;
212 
213     np = (SQLPNODE *) calloc(1, sizeof(SQLPNODE));
214     return np;
215 }
216 
sqpNewExpressionNode(int oper,SQLPNODE * left,SQLPNODE * right)217 SQLPNODE *sqpNewExpressionNode(int oper, SQLPNODE * left, SQLPNODE * right)
218 {
219     SQLPNODE *np;
220 
221     np = sqpNewNode();
222 
223     np->node_type = SQLP_NODE_EXPRESSION;
224     np->oper = oper;
225     np->left = left;
226     np->right = right;
227 
228     return np;
229 }
230 
sqpNewColumnNode(char * name)231 SQLPNODE *sqpNewColumnNode(char *name)
232 {
233     SQLPNODE *np;
234 
235     np = sqpNewNode();
236 
237     np->node_type = SQLP_NODE_COLUMN;
238     np->column_name = strdup(name);
239 
240     return np;
241 }
242 
sqpNewValueNode(char * strval,int intval,double dblval,int type)243 SQLPNODE *sqpNewValueNode(char *strval, int intval, double dblval, int type)
244 {
245     SQLPNODE *np;
246 
247     np = sqpNewNode();
248 
249     np->node_type = SQLP_NODE_VALUE;
250 
251     np->value.type = type;
252     if (strval)
253 	np->value.s = strdup(strval);
254     np->value.i = intval;
255     np->value.d = dblval;
256 
257     return np;
258 }
259 
sqpFreeNode(SQLPNODE * np)260 void sqpFreeNode(SQLPNODE * np)
261 {
262     if (!np)
263 	return;
264 
265     if (np->left)
266 	sqpFreeNode(np->left);
267 
268     if (np->right)
269 	sqpFreeNode(np->right);
270 
271     if (np->column_name)
272 	free(np->column_name);
273 
274     if (np->value.s)
275 	free(np->value.s);
276 
277     free(np);
278 }
279 
sqpOperatorCode(char * oper)280 int sqpOperatorCode(char *oper)
281 {
282     char *tmp, *ptr;
283 
284     /* Convert to lower case */
285     tmp = strdup(oper);
286     ptr = tmp;
287     while (*ptr) {
288 	*ptr = tolower(*ptr);
289 	ptr++;
290     }
291 
292     if (strcmp(oper, "=") == 0)
293 	return SQLP_EQ;
294     else if (strcmp(oper, "<") == 0)
295 	return SQLP_LT;
296     else if (strcmp(oper, "<=") == 0)
297 	return SQLP_LE;
298     else if (strcmp(oper, ">") == 0)
299 	return SQLP_GT;
300     else if (strcmp(oper, ">=") == 0)
301 	return SQLP_GE;
302     else if (strcmp(oper, "<>") == 0)
303 	return SQLP_NE;
304     else if (strcmp(oper, "~") == 0)
305 	return SQLP_MTCH;
306     else if (strcmp(oper, "+") == 0)
307 	return SQLP_ADD;
308     else if (strcmp(oper, "-") == 0)
309 	return SQLP_SUBTR;
310     else if (strcmp(oper, "*") == 0)
311 	return SQLP_MLTP;
312     else if (strcmp(oper, "/") == 0)
313 	return SQLP_DIV;
314     else if (strcmp(oper, "and") == 0)
315 	return SQLP_AND;
316     else if (strcmp(oper, "or") == 0)
317 	return SQLP_OR;
318     else if (strcmp(oper, "not") == 0)
319 	return SQLP_NOT;
320 
321     free(tmp);
322 
323     return 0;
324 }
325 
sqpOperatorName(int oper)326 char *sqpOperatorName(int oper)
327 {
328     switch (oper) {
329     case SQLP_EQ:
330 	return "=";
331 	break;
332     case SQLP_LT:
333 	return "<";
334 	break;
335     case SQLP_LE:
336 	return "<=";
337 	break;
338     case SQLP_GT:
339 	return ">";
340 	break;
341     case SQLP_GE:
342 	return ">=";
343 	break;
344     case SQLP_NE:
345 	return "<>";
346 	break;
347     case SQLP_MTCH:
348 	return "~";
349 	break;
350     case SQLP_ADD:
351 	return "+";
352 	break;
353     case SQLP_SUBTR:
354 	return "-";
355 	break;
356     case SQLP_MLTP:
357 	return "*";
358 	break;
359     case SQLP_DIV:
360 	return "/";
361 	break;
362     case SQLP_AND:
363 	return "AND";
364 	break;
365     case SQLP_OR:
366 	return "OR";
367 	break;
368     case SQLP_NOT:
369 	return "NOT";
370 	break;
371     }
372     return "?";
373 }
374