GRASS Programmer's Manual
6.4.1(2011)
|
00001 00002 /***************************************************************************** 00003 * 00004 * MODULE: SQL statement parser library 00005 * 00006 * AUTHOR(S): lex.l and yac.y were originaly taken from unixODBC and 00007 * probably written by Peter Harvey <pharvey@codebydesigns.com>, 00008 * original modifications & added code by 00009 * Radim Blazek <radim.blazek gmail.com> 00010 * Glynn Clements <glynn gclements.plus.com>, 00011 * Markus Neteler <neteler itc.it>, 00012 * Martin Landa <landa.martin gmail.com>, 00013 * Moritz Lennert <mlennert club.worldonline.be>, 00014 * Hamish Bowman <hamish_nospam yahoo.com>, 00015 * Daniel Calvelo Aros <dca.gis gmail.com>, 00016 * Paul Kelly <paul-grass stjohnspoint.co.uk>, 00017 * Alex Shevlakov <sixote yahoo.com> 00018 * 00019 * PURPOSE: Parse input string containing SQL statement to 00020 * SQLPSTMT structure. 00021 * SQL parser may be used by simple database drivers. 00022 * 00023 * COPYRIGHT: (C) 2000-2007 by the GRASS Development Team 00024 * 00025 * This program is free software under the GNU General Public 00026 * License (>=v2). Read the file COPYING that comes with GRASS 00027 * for details. 00028 * 00029 *****************************************************************************/ 00030 00031 #define SQLP_MAIN 00032 00033 #include <stdlib.h> 00034 #include <stdio.h> 00035 #include <string.h> 00036 #include <ctype.h> 00037 #include <assert.h> 00038 #include <grass/sqlp.h> 00039 00040 /* save string to value */ 00041 int sqpSaveStr(SQLPVALUE * val, char *c) 00042 { 00043 int len = 0; 00044 00045 len = strlen(c) + 1; 00046 val->s = (char *)realloc(val->s, len); 00047 00048 strcpy(val->s, c); 00049 00050 return (1); 00051 } 00052 00053 void sqpInitValue(SQLPVALUE * val) 00054 { 00055 val->type = SQLP_NULL; 00056 val->s = NULL; 00057 val->i = 0; 00058 val->d = 0.0; 00059 } 00060 00061 void sqpCopyValue(SQLPVALUE * from, SQLPVALUE * to) 00062 { 00063 to->type = from->type; 00064 00065 if (to->s) 00066 free(to->s); 00067 00068 if (from->s) 00069 to->s = strdup(from->s); 00070 00071 to->i = from->i; 00072 to->d = from->d; 00073 } 00074 00075 int sqpInitParser(SQLPSTMT * st) 00076 { 00077 sqlpStmt = st; 00078 sqlpStmt->cur = sqlpStmt->stmt; 00079 00080 sqlpStmt->errmsg[0] = '\0'; 00081 sqlpStmt->table[0] = '\0'; 00082 sqlpStmt->nCol = 0; 00083 sqlpStmt->nVal = 0; 00084 sqlpStmt->upperNodeptr = NULL; 00085 sqlpStmt->orderCol = NULL; 00086 00087 return (1); 00088 } 00089 00090 void sqpCommand(int command) 00091 { 00092 sqlpStmt->command = command; 00093 return; 00094 } 00095 00096 void sqpTable(char *tbl) 00097 { 00098 strncpy(sqlpStmt->table, tbl, SQLP_MAX_TABLE); 00099 return; 00100 } 00101 00102 void sqpColumn(char *col) 00103 { 00104 int i; 00105 00106 i = sqlpStmt->nCol; 00107 sqpAllocCol(sqlpStmt, i + 1); 00108 sqpSaveStr(&(sqlpStmt->Col[i]), col); 00109 00110 sqlpStmt->nCol++; 00111 return; 00112 } 00113 00114 void sqpColumnDef(char *col, int type, int width, int decimals) 00115 { 00116 int i; 00117 00118 i = sqlpStmt->nCol; 00119 sqpAllocCol(sqlpStmt, i + 1); 00120 sqpSaveStr(&(sqlpStmt->Col[i]), col); 00121 sqlpStmt->ColType[i] = type; 00122 sqlpStmt->ColWidth[i] = width; 00123 sqlpStmt->ColDecim[i] = decimals; 00124 00125 sqlpStmt->nCol++; 00126 return; 00127 } 00128 00129 void sqpValue(char *strval, int intval, double dblval, int type) 00130 { 00131 int i; 00132 00133 i = sqlpStmt->nVal; 00134 00135 /* allocate space for cols because if in INSERT cols were not 00136 * specified array for ColNum would not be allocated */ 00137 sqpAllocCol(sqlpStmt, i + 1); 00138 00139 sqpAllocVal(sqlpStmt, i + 1); 00140 sqlpStmt->Val[i].s = NULL; 00141 sqlpStmt->Val[i].i = 0; /* not necessay I think */ 00142 sqlpStmt->Val[i].d = 0.0; /* not necessay I think */ 00143 00144 sqlpStmt->Val[i].type = type; 00145 switch (type) { 00146 case (SQLP_S): 00147 sqpSaveStr(&(sqlpStmt->Val[i]), strval); 00148 break; 00149 case (SQLP_I): 00150 sqlpStmt->Val[i].i = intval; 00151 break; 00152 case (SQLP_D): 00153 sqlpStmt->Val[i].d = dblval; 00154 break; 00155 /* SQLP_NULL, nothing to do */ 00156 } 00157 00158 sqlpStmt->nVal++; 00159 return; 00160 } 00161 00162 void sqpAssignment(char *col, char *strval, int intval, double dblval, 00163 SQLPNODE * expval, int type) 00164 { 00165 int i; 00166 00167 i = sqlpStmt->nCol; 00168 00169 sqpAllocCol(sqlpStmt, i + 1); 00170 sqpSaveStr(&(sqlpStmt->Col[i]), col); 00171 00172 sqpAllocVal(sqlpStmt, i + 1); 00173 sqlpStmt->Val[i].s = NULL; 00174 sqlpStmt->Val[i].i = 0; /* not necessay I think */ 00175 sqlpStmt->Val[i].d = 0.0; /* not necessay I think */ 00176 00177 sqlpStmt->Val[i].type = type; 00178 switch (type) { 00179 case (SQLP_S): 00180 sqpSaveStr(&(sqlpStmt->Val[i]), strval); 00181 break; 00182 case (SQLP_I): 00183 sqlpStmt->Val[i].i = intval; 00184 break; 00185 case (SQLP_D): 00186 sqlpStmt->Val[i].d = dblval; 00187 break; 00188 case (SQLP_EXPR): 00189 sqlpStmt->Val[i].expr = expval; 00190 /* Don't do anything right now; come back to this when executing */ 00191 break; 00192 /* SQLP_NULL, nothing to do */ 00193 } 00194 00195 sqlpStmt->nCol++; 00196 sqlpStmt->nVal++; 00197 return; 00198 } 00199 00200 void sqpOrderColumn(char *col, int dir) 00201 { 00202 sqlpStmt->orderCol = (char *)realloc(sqlpStmt->orderCol, strlen(col) + 1); 00203 strcpy(sqlpStmt->orderCol, col); 00204 sqlpStmt->orderDir = dir; 00205 return; 00206 } 00207 00208 /* Create and init new node */ 00209 SQLPNODE *sqpNewNode(void) 00210 { 00211 SQLPNODE *np; 00212 00213 np = (SQLPNODE *) calloc(1, sizeof(SQLPNODE)); 00214 return np; 00215 } 00216 00217 SQLPNODE *sqpNewExpressionNode(int oper, SQLPNODE * left, SQLPNODE * right) 00218 { 00219 SQLPNODE *np; 00220 00221 np = sqpNewNode(); 00222 00223 np->node_type = SQLP_NODE_EXPRESSION; 00224 np->oper = oper; 00225 np->left = left; 00226 np->right = right; 00227 00228 return np; 00229 } 00230 00231 SQLPNODE *sqpNewColumnNode(char *name) 00232 { 00233 SQLPNODE *np; 00234 00235 np = sqpNewNode(); 00236 00237 np->node_type = SQLP_NODE_COLUMN; 00238 np->column_name = strdup(name); 00239 00240 return np; 00241 } 00242 00243 SQLPNODE *sqpNewValueNode(char *strval, int intval, double dblval, int type) 00244 { 00245 SQLPNODE *np; 00246 00247 np = sqpNewNode(); 00248 00249 np->node_type = SQLP_NODE_VALUE; 00250 00251 np->value.type = type; 00252 if (strval) 00253 np->value.s = strdup(strval); 00254 np->value.i = intval; 00255 np->value.d = dblval; 00256 00257 return np; 00258 } 00259 00260 void sqpFreeNode(SQLPNODE * np) 00261 { 00262 if (!np) 00263 return; 00264 00265 if (np->left) 00266 sqpFreeNode(np->left); 00267 00268 if (np->right) 00269 sqpFreeNode(np->right); 00270 00271 if (np->column_name) 00272 free(np->column_name); 00273 00274 if (np->value.s) 00275 free(np->value.s); 00276 00277 free(np); 00278 } 00279 00280 int sqpOperatorCode(char *oper) 00281 { 00282 char *tmp, *ptr; 00283 00284 /* Convert to lower case */ 00285 tmp = strdup(oper); 00286 ptr = tmp; 00287 while (*ptr) { 00288 *ptr = tolower(*ptr); 00289 ptr++; 00290 } 00291 00292 if (strcmp(oper, "=") == 0) 00293 return SQLP_EQ; 00294 else if (strcmp(oper, "<") == 0) 00295 return SQLP_LT; 00296 else if (strcmp(oper, "<=") == 0) 00297 return SQLP_LE; 00298 else if (strcmp(oper, ">") == 0) 00299 return SQLP_GT; 00300 else if (strcmp(oper, ">=") == 0) 00301 return SQLP_GE; 00302 else if (strcmp(oper, "<>") == 0) 00303 return SQLP_NE; 00304 else if (strcmp(oper, "~") == 0) 00305 return SQLP_MTCH; 00306 else if (strcmp(oper, "+") == 0) 00307 return SQLP_ADD; 00308 else if (strcmp(oper, "-") == 0) 00309 return SQLP_SUBTR; 00310 else if (strcmp(oper, "*") == 0) 00311 return SQLP_MLTP; 00312 else if (strcmp(oper, "/") == 0) 00313 return SQLP_DIV; 00314 else if (strcmp(oper, "and") == 0) 00315 return SQLP_AND; 00316 else if (strcmp(oper, "or") == 0) 00317 return SQLP_OR; 00318 else if (strcmp(oper, "not") == 0) 00319 return SQLP_NOT; 00320 00321 free(tmp); 00322 00323 return 0; 00324 } 00325 00326 char *sqpOperatorName(int oper) 00327 { 00328 switch (oper) { 00329 case SQLP_EQ: 00330 return "="; 00331 break; 00332 case SQLP_LT: 00333 return "<"; 00334 break; 00335 case SQLP_LE: 00336 return "<="; 00337 break; 00338 case SQLP_GT: 00339 return ">"; 00340 break; 00341 case SQLP_GE: 00342 return ">="; 00343 break; 00344 case SQLP_NE: 00345 return "<>"; 00346 break; 00347 case SQLP_MTCH: 00348 return "~"; 00349 break; 00350 case SQLP_ADD: 00351 return "+"; 00352 break; 00353 case SQLP_SUBTR: 00354 return "-"; 00355 break; 00356 case SQLP_MLTP: 00357 return "*"; 00358 break; 00359 case SQLP_DIV: 00360 return "/"; 00361 break; 00362 case SQLP_AND: 00363 return "AND"; 00364 break; 00365 case SQLP_OR: 00366 return "OR"; 00367 break; 00368 case SQLP_NOT: 00369 return "NOT"; 00370 break; 00371 } 00372 return "?"; 00373 }