sql.c

Go to the documentation of this file.
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 }