sql.c

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

Generated on Sun Apr 6 17:31:38 2008 for GRASS by  doxygen 1.5.5