GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
sql.c
Go to the documentation of this file.
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 
39 
40 /* save string to value */
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 
54 {
55  val->type = SQLP_NULL;
56  val->s = NULL;
57  val->i = 0;
58  val->d = 0.0;
59 }
60 
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 
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 
90 void sqpCommand(int command)
91 {
92  sqlpStmt->command = command;
93  return;
94 }
95 
96 void sqpTable(char *tbl)
97 {
98  strncpy(sqlpStmt->table, tbl, SQLP_MAX_TABLE);
99  return;
100 }
101 
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 
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 
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 
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 
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 */
210 {
211  SQLPNODE *np;
212 
213  np = (SQLPNODE *) calloc(1, sizeof(SQLPNODE));
214  return np;
215 }
216 
217 SQLPNODE *sqpNewExpressionNode(int oper, SQLPNODE * left, SQLPNODE * right)
218 {
219  SQLPNODE *np;
220 
221  np = sqpNewNode();
222 
224  np->oper = oper;
225  np->left = left;
226  np->right = right;
227 
228  return np;
229 }
230 
232 {
233  SQLPNODE *np;
234 
235  np = sqpNewNode();
236 
238  np->column_name = strdup(name);
239 
240  return np;
241 }
242 
243 SQLPNODE *sqpNewValueNode(char *strval, int intval, double dblval, int type)
244 {
245  SQLPNODE *np;
246 
247  np = sqpNewNode();
248 
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 
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 
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 
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 }
Definition: sqlp.h:70
int nVal
Definition: sqlp.h:104
SQLPVALUE * Val
Definition: sqlp.h:102
struct sqlpnode * expr
Definition: sqlp.h:76
SQLPVALUE * Col
Definition: sqlp.h:96
char * cur
Definition: sqlp.h:92
int type
Definition: sqlp.h:72
int orderDir
Definition: sqlp.h:107
void sqpColumn(char *col)
Definition: sql.c:102
char * stmt
Definition: sqlp.h:91
#define SQLP_NODE_EXPRESSION
Definition: sqlp.h:63
#define SQLP_EXPR
Definition: sqlp.h:48
double d
Definition: sqlp.h:75
void sqpFreeNode(SQLPNODE *np)
Definition: sql.c:260
SQLPNODE * sqpNewColumnNode(char *name)
Definition: sql.c:231
int sqpInitParser(SQLPSTMT *st)
Definition: sql.c:75
int oper
Definition: sqlp.h:82
void sqpColumnDef(char *col, int type, int width, int decimals)
Definition: sql.c:114
void sqpInitValue(SQLPVALUE *val)
Definition: sql.c:53
Definition: sqlp.h:89
int * ColType
Definition: sqlp.h:97
char errmsg[SQLP_MAX_ERR+1]
Definition: sqlp.h:93
void free(void *)
#define NULL
Definition: ccmath.h:32
char table[SQLP_MAX_TABLE+1]
Definition: sqlp.h:95
char * sqpOperatorName(int oper)
Definition: sql.c:326
#define SQLP_ADD
Definition: sqlp.h:20
#define SQLP_MLTP
Definition: sqlp.h:22
#define SQLP_GT
Definition: sqlp.h:29
int * ColDecim
Definition: sqlp.h:99
int sqpOperatorCode(char *oper)
Definition: sql.c:280
#define SQLP_SUBTR
Definition: sqlp.h:21
void sqpTable(char *tbl)
Definition: sql.c:96
struct state * st
Definition: parser.c:104
SQLPNODE * sqpNewValueNode(char *strval, int intval, double dblval, int type)
Definition: sql.c:243
SQLPVALUE value
Definition: sqlp.h:86
SQLPNODE * sqpNewNode(void)
Definition: sql.c:209
#define SQLP_I
Definition: sqlp.h:45
#define SQLP_S
Definition: sqlp.h:44
SQLPNODE * upperNodeptr
Definition: sqlp.h:105
#define SQLP_NE
Definition: sqlp.h:31
#define SQLP_OR
Definition: sqlp.h:39
int sqpAllocCol(SQLPSTMT *st, int n)
Definition: db/sqlp/alloc.c:37
int * ColWidth
Definition: sqlp.h:98
int nCol
Definition: sqlp.h:101
#define SQLP_MTCH
Definition: sqlp.h:32
Definition: sqlp.h:79
int command
Definition: sqlp.h:94
void sqpOrderColumn(char *col, int dir)
Definition: sql.c:200
void sqpCopyValue(SQLPVALUE *from, SQLPVALUE *to)
Definition: sql.c:61
char * column_name
Definition: sqlp.h:85
#define SQLP_EQ
Definition: sqlp.h:26
#define SQLP_AND
Definition: sqlp.h:38
int i
Definition: sqlp.h:74
SQLPSTMT * sqlpStmt
Definition: sql.c:38
int sqpAllocVal(SQLPSTMT *st, int n)
Definition: db/sqlp/alloc.c:58
SQLPNODE * sqpNewExpressionNode(int oper, SQLPNODE *left, SQLPNODE *right)
Definition: sql.c:217
#define SQLP_NULL
Definition: sqlp.h:43
int sqpSaveStr(SQLPVALUE *val, char *c)
Definition: sql.c:41
#define SQLP_DIV
Definition: sqlp.h:23
char * s
Definition: sqlp.h:73
#define SQLP_LE
Definition: sqlp.h:28
void sqpAssignment(char *col, char *strval, int intval, double dblval, SQLPNODE *expval, int type)
Definition: sql.c:162
int node_type
Definition: sqlp.h:81
const char * name
Definition: named_colr.c:7
struct sqlpnode * left
Definition: sqlp.h:83
void sqpValue(char *strval, int intval, double dblval, int type)
Definition: sql.c:129
#define SQLP_NODE_COLUMN
Definition: sqlp.h:61
char * orderCol
Definition: sqlp.h:106
#define SQLP_MAX_TABLE
Definition: sqlp.h:57
#define SQLP_NODE_VALUE
Definition: sqlp.h:62
#define SQLP_GE
Definition: sqlp.h:30
#define SQLP_D
Definition: sqlp.h:46
void sqpCommand(int command)
Definition: sql.c:90
struct sqlpnode * right
Definition: sqlp.h:84
#define SQLP_NOT
Definition: sqlp.h:40
#define SQLP_LT
Definition: sqlp.h:27