sql.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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 GRASS
  26. * for details.
  27. *
  28. *****************************************************************************/
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <assert.h>
  34. #include <grass/sqlp.h>
  35. SQLPSTMT *sqlpStmt;
  36. /* save string to value */
  37. int sqpSaveStr(SQLPVALUE * val, char *c)
  38. {
  39. int len = 0;
  40. len = strlen(c) + 1;
  41. val->s = (char *)realloc(val->s, len);
  42. strcpy(val->s, c);
  43. return (1);
  44. }
  45. void sqpInitValue(SQLPVALUE * val)
  46. {
  47. val->type = SQLP_NULL;
  48. val->s = NULL;
  49. val->i = 0;
  50. val->d = 0.0;
  51. }
  52. void sqpCopyValue(SQLPVALUE * from, SQLPVALUE * to)
  53. {
  54. to->type = from->type;
  55. if (to->s)
  56. free(to->s);
  57. if (from->s)
  58. to->s = strdup(from->s);
  59. to->i = from->i;
  60. to->d = from->d;
  61. }
  62. int sqpInitParser(SQLPSTMT * st)
  63. {
  64. sqlpStmt = st;
  65. sqlpStmt->cur = sqlpStmt->stmt;
  66. sqlpStmt->errmsg[0] = '\0';
  67. sqlpStmt->table[0] = '\0';
  68. sqlpStmt->nCol = 0;
  69. sqlpStmt->nVal = 0;
  70. sqlpStmt->upperNodeptr = NULL;
  71. sqlpStmt->orderCol = NULL;
  72. return (1);
  73. }
  74. void sqpCommand(int command)
  75. {
  76. sqlpStmt->command = command;
  77. return;
  78. }
  79. void sqpTable(char *tbl)
  80. {
  81. strncpy(sqlpStmt->table, tbl, SQLP_MAX_TABLE);
  82. return;
  83. }
  84. void sqpColumn(char *col)
  85. {
  86. int i;
  87. i = sqlpStmt->nCol;
  88. sqpAllocCol(sqlpStmt, i + 1);
  89. sqpSaveStr(&(sqlpStmt->Col[i]), col);
  90. sqlpStmt->nCol++;
  91. return;
  92. }
  93. void sqpColumnDef(char *col, int type, int width, int decimals)
  94. {
  95. int i;
  96. i = sqlpStmt->nCol;
  97. sqpAllocCol(sqlpStmt, i + 1);
  98. sqpSaveStr(&(sqlpStmt->Col[i]), col);
  99. sqlpStmt->ColType[i] = type;
  100. sqlpStmt->ColWidth[i] = width;
  101. sqlpStmt->ColDecim[i] = decimals;
  102. sqlpStmt->nCol++;
  103. return;
  104. }
  105. void sqpValue(char *strval, int intval, double dblval, int type)
  106. {
  107. int i;
  108. i = sqlpStmt->nVal;
  109. /* allocate space for cols because if in INSERT cols were not
  110. * specified array for ColNum would not be allocated */
  111. sqpAllocCol(sqlpStmt, i + 1);
  112. sqpAllocVal(sqlpStmt, i + 1);
  113. sqlpStmt->Val[i].s = NULL;
  114. sqlpStmt->Val[i].i = 0; /* not necessay I think */
  115. sqlpStmt->Val[i].d = 0.0; /* not necessay I think */
  116. sqlpStmt->Val[i].type = type;
  117. switch (type) {
  118. case (SQLP_S):
  119. sqpSaveStr(&(sqlpStmt->Val[i]), strval);
  120. break;
  121. case (SQLP_I):
  122. sqlpStmt->Val[i].i = intval;
  123. break;
  124. case (SQLP_D):
  125. sqlpStmt->Val[i].d = dblval;
  126. break;
  127. /* SQLP_NULL, nothing to do */
  128. }
  129. sqlpStmt->nVal++;
  130. return;
  131. }
  132. void sqpAssignment(char *col, char *strval, int intval, double dblval,
  133. SQLPNODE * expval, int type)
  134. {
  135. int i;
  136. i = sqlpStmt->nCol;
  137. sqpAllocCol(sqlpStmt, i + 1);
  138. sqpSaveStr(&(sqlpStmt->Col[i]), col);
  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. 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. case (SQLP_EXPR):
  155. sqlpStmt->Val[i].expr = expval;
  156. /* Don't do anything right now; come back to this when executing */
  157. break;
  158. /* SQLP_NULL, nothing to do */
  159. }
  160. sqlpStmt->nCol++;
  161. sqlpStmt->nVal++;
  162. return;
  163. }
  164. void sqpOrderColumn(char *col, int dir)
  165. {
  166. sqlpStmt->orderCol = (char *)realloc(sqlpStmt->orderCol, strlen(col) + 1);
  167. strcpy(sqlpStmt->orderCol, col);
  168. sqlpStmt->orderDir = dir;
  169. return;
  170. }
  171. /* Create and init new node */
  172. SQLPNODE *sqpNewNode(void)
  173. {
  174. SQLPNODE *np;
  175. np = (SQLPNODE *) calloc(1, sizeof(SQLPNODE));
  176. return np;
  177. }
  178. SQLPNODE *sqpNewExpressionNode(int oper, SQLPNODE * left, SQLPNODE * right)
  179. {
  180. SQLPNODE *np;
  181. np = sqpNewNode();
  182. np->node_type = SQLP_NODE_EXPRESSION;
  183. np->oper = oper;
  184. np->left = left;
  185. np->right = right;
  186. return np;
  187. }
  188. SQLPNODE *sqpNewColumnNode(char *name)
  189. {
  190. SQLPNODE *np;
  191. np = sqpNewNode();
  192. np->node_type = SQLP_NODE_COLUMN;
  193. np->column_name = strdup(name);
  194. return np;
  195. }
  196. SQLPNODE *sqpNewValueNode(char *strval, int intval, double dblval, int type)
  197. {
  198. SQLPNODE *np;
  199. np = sqpNewNode();
  200. np->node_type = SQLP_NODE_VALUE;
  201. np->value.type = type;
  202. if (strval)
  203. np->value.s = strdup(strval);
  204. np->value.i = intval;
  205. np->value.d = dblval;
  206. return np;
  207. }
  208. void sqpFreeNode(SQLPNODE * np)
  209. {
  210. if (!np)
  211. return;
  212. if (np->left)
  213. sqpFreeNode(np->left);
  214. if (np->right)
  215. sqpFreeNode(np->right);
  216. if (np->column_name)
  217. free(np->column_name);
  218. if (np->value.s)
  219. free(np->value.s);
  220. free(np);
  221. }
  222. int sqpOperatorCode(char *oper)
  223. {
  224. char *tmp, *ptr;
  225. /* Convert to lower case */
  226. tmp = strdup(oper);
  227. ptr = tmp;
  228. while (*ptr) {
  229. *ptr = tolower(*ptr);
  230. ptr++;
  231. }
  232. if (strcmp(oper, "=") == 0)
  233. return SQLP_EQ;
  234. else if (strcmp(oper, "<") == 0)
  235. return SQLP_LT;
  236. else if (strcmp(oper, "<=") == 0)
  237. return SQLP_LE;
  238. else if (strcmp(oper, ">") == 0)
  239. return SQLP_GT;
  240. else if (strcmp(oper, ">=") == 0)
  241. return SQLP_GE;
  242. else if (strcmp(oper, "<>") == 0)
  243. return SQLP_NE;
  244. else if (strcmp(oper, "~") == 0)
  245. return SQLP_MTCH;
  246. else if (strcmp(oper, "+") == 0)
  247. return SQLP_ADD;
  248. else if (strcmp(oper, "-") == 0)
  249. return SQLP_SUBTR;
  250. else if (strcmp(oper, "*") == 0)
  251. return SQLP_MLTP;
  252. else if (strcmp(oper, "/") == 0)
  253. return SQLP_DIV;
  254. else if (strcmp(oper, "and") == 0)
  255. return SQLP_AND;
  256. else if (strcmp(oper, "or") == 0)
  257. return SQLP_OR;
  258. else if (strcmp(oper, "not") == 0)
  259. return SQLP_NOT;
  260. free(tmp);
  261. return 0;
  262. }
  263. char *sqpOperatorName(int oper)
  264. {
  265. switch (oper) {
  266. case SQLP_EQ:
  267. return "=";
  268. break;
  269. case SQLP_LT:
  270. return "<";
  271. break;
  272. case SQLP_LE:
  273. return "<=";
  274. break;
  275. case SQLP_GT:
  276. return ">";
  277. break;
  278. case SQLP_GE:
  279. return ">=";
  280. break;
  281. case SQLP_NE:
  282. return "<>";
  283. break;
  284. case SQLP_MTCH:
  285. return "~";
  286. break;
  287. case SQLP_ADD:
  288. return "+";
  289. break;
  290. case SQLP_SUBTR:
  291. return "-";
  292. break;
  293. case SQLP_MLTP:
  294. return "*";
  295. break;
  296. case SQLP_DIV:
  297. return "/";
  298. break;
  299. case SQLP_AND:
  300. return "AND";
  301. break;
  302. case SQLP_OR:
  303. return "OR";
  304. break;
  305. case SQLP_NOT:
  306. return "NOT";
  307. break;
  308. }
  309. return "?";
  310. }