sql.c 7.8 KB

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