/***************************************************************************** * * MODULE: SQL statement parser library * * AUTHOR(S): lex.l and yac.y were originaly taken from unixODBC and * probably written by Peter Harvey , * original modifications & added code by * Radim Blazek * Glynn Clements , * Markus Neteler , * Martin Landa , * Moritz Lennert , * Hamish Bowman , * Daniel Calvelo Aros , * Paul Kelly , * Alex Shevlakov * * PURPOSE: Parse input string containing SQL statement to * SQLPSTMT structure. * SQL parser may be used by simple database drivers. * * COPYRIGHT: (C) 2000-2007 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #define SQLP_MAIN #include #include #include #include #include #include /* save string to value */ int sqpSaveStr(SQLPVALUE *val, char *c ) { int len = 0; len = strlen ( c ) + 1; val->s = (char *) realloc (val->s, len); strcpy ( val->s, c ); return (1); } void sqpInitValue ( SQLPVALUE *val) { val->type = SQLP_NULL; val->s = NULL; val->i = 0; val->d = 0.0; } void sqpCopyValue ( SQLPVALUE *from, SQLPVALUE *to) { to->type = from->type; if ( to->s ) free ( to->s ); if ( from->s ) to->s = strdup ( from->s ); to->i = from->i; to->d = from->d; } int sqpInitParser(SQLPSTMT *st) { sqlpStmt = st; sqlpStmt->cur = sqlpStmt->stmt; sqlpStmt->errmsg[0] = '\0'; sqlpStmt->table[0] = '\0'; sqlpStmt->nCol = 0; sqlpStmt->nVal = 0; sqlpStmt->upperNodeptr = NULL; sqlpStmt->orderCol = NULL; return (1); } void sqpCommand( int command ) { sqlpStmt->command = command; return; } void sqpTable( char *tbl ) { strncpy (sqlpStmt->table, tbl, SQLP_MAX_TABLE ); return; } void sqpColumn( char *col ) { int i; i = sqlpStmt->nCol; sqpAllocCol(sqlpStmt, i + 1 ); sqpSaveStr ( &(sqlpStmt->Col[i]), col ); sqlpStmt->nCol++; return; } void sqpColumnDef( char *col, int type, int width, int decimals ) { int i; i = sqlpStmt->nCol; sqpAllocCol(sqlpStmt, i + 1 ); sqpSaveStr ( &(sqlpStmt->Col[i]), col ); sqlpStmt->ColType[i] = type; sqlpStmt->ColWidth[i] = width; sqlpStmt->ColDecim[i] = decimals; sqlpStmt->nCol++; return; } void sqpValue( char *strval, int intval, double dblval, int type ) { int i; i = sqlpStmt->nVal; /* allocate space for cols because if in INSERT cols were not * specified array for ColNum would not be allocated */ sqpAllocCol(sqlpStmt, i + 1 ); sqpAllocVal(sqlpStmt, i + 1 ); sqlpStmt->Val[i].s = NULL; sqlpStmt->Val[i].i = 0; /* not necessay I think */ sqlpStmt->Val[i].d = 0.0; /* not necessay I think */ sqlpStmt->Val[i].type = type; switch ( type ) { case (SQLP_S): sqpSaveStr ( &(sqlpStmt->Val[i]), strval ); break; case (SQLP_I): sqlpStmt->Val[i].i = intval; break; case (SQLP_D): sqlpStmt->Val[i].d = dblval; break; /* SQLP_NULL, nothing to do */ } sqlpStmt->nVal++; return; } void sqpAssignment( char *col, char *strval, int intval, double dblval, SQLPNODE *expval, int type ) { int i; i = sqlpStmt->nCol; sqpAllocCol(sqlpStmt, i + 1 ); sqpSaveStr ( &(sqlpStmt->Col[i]), col ); sqpAllocVal(sqlpStmt, i + 1 ); sqlpStmt->Val[i].s = NULL; sqlpStmt->Val[i].i = 0; /* not necessay I think */ sqlpStmt->Val[i].d = 0.0; /* not necessay I think */ sqlpStmt->Val[i].type = type; switch ( type ) { case (SQLP_S): sqpSaveStr ( &(sqlpStmt->Val[i]), strval ); break; case (SQLP_I): sqlpStmt->Val[i].i = intval; break; case (SQLP_D): sqlpStmt->Val[i].d = dblval; break; case (SQLP_EXPR): sqlpStmt->Val[i].expr = expval; /* Don't do anything right now; come back to this when executing */ break; /* SQLP_NULL, nothing to do */ } sqlpStmt->nCol++; sqlpStmt->nVal++; return; } void sqpOrderColumn( char *col, int dir ) { sqlpStmt->orderCol = (char *) realloc (sqlpStmt->orderCol, strlen(col)+1); strcpy ( sqlpStmt->orderCol, col ); sqlpStmt->orderDir = dir; return; } /* Create and init new node */ SQLPNODE *sqpNewNode ( void ) { SQLPNODE *np; np = (SQLPNODE *) calloc ( 1, sizeof (SQLPNODE) ); return np; } SQLPNODE * sqpNewExpressionNode (int oper, SQLPNODE *left, SQLPNODE *right) { SQLPNODE *np; np = sqpNewNode (); np->node_type = SQLP_NODE_EXPRESSION; np->oper = oper; np->left = left; np->right = right; return np; } SQLPNODE * sqpNewColumnNode ( char *name ) { SQLPNODE *np; np = sqpNewNode (); np->node_type = SQLP_NODE_COLUMN; np->column_name = strdup ( name ); return np; } SQLPNODE * sqpNewValueNode (char *strval, int intval, double dblval, int type) { SQLPNODE *np; np = sqpNewNode (); np->node_type = SQLP_NODE_VALUE; np->value.type = type; if ( strval ) np->value.s = strdup ( strval ); np->value.i = intval; np->value.d = dblval; return np; } void sqpFreeNode ( SQLPNODE *np ) { if ( !np ) return; if ( np->left ) sqpFreeNode ( np->left ); if ( np->right ) sqpFreeNode ( np->right ); if ( np->column_name ) free ( np->column_name ); if ( np->value.s ) free ( np->value.s ); free ( np ); } int sqpOperatorCode( char *oper) { char *tmp, *ptr; /* Convert to lower case */ tmp = strdup ( oper ); ptr = tmp; while ( *ptr ) { *ptr = tolower ( *ptr ); ptr++; } if ( strcmp ( oper, "=") == 0 ) return SQLP_EQ; else if ( strcmp ( oper, "<") == 0 ) return SQLP_LT; else if ( strcmp ( oper, "<=") == 0 ) return SQLP_LE; else if ( strcmp ( oper, ">") == 0 ) return SQLP_GT; else if ( strcmp ( oper, ">=") == 0 ) return SQLP_GE; else if ( strcmp ( oper, "<>") == 0 ) return SQLP_NE; else if ( strcmp ( oper, "~") == 0 ) return SQLP_MTCH; else if ( strcmp ( oper, "+") == 0 ) return SQLP_ADD; else if ( strcmp ( oper, "-") == 0 ) return SQLP_SUBTR; else if ( strcmp ( oper, "*") == 0 ) return SQLP_MLTP; else if ( strcmp ( oper, "/") == 0 ) return SQLP_DIV; else if ( strcmp ( oper, "and") == 0 ) return SQLP_AND; else if ( strcmp ( oper, "or") == 0 ) return SQLP_OR; else if ( strcmp ( oper, "not") == 0 ) return SQLP_NOT; free ( tmp ); return 0; } char * sqpOperatorName( int oper ) { switch ( oper ) { case SQLP_EQ: return "="; break; case SQLP_LT: return "<"; break; case SQLP_LE: return "<="; break; case SQLP_GT: return ">"; break; case SQLP_GE: return ">="; break; case SQLP_NE: return "<>"; break; case SQLP_MTCH: return "~"; break; case SQLP_ADD: return "+"; break; case SQLP_SUBTR: return "-"; break; case SQLP_MLTP: return "*"; break; case SQLP_DIV: return "/"; break; case SQLP_AND: return "AND"; break; case SQLP_OR: return "OR"; break; case SQLP_NOT: return "NOT"; break; } return "?"; }