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