/***************************************************************************** * * MODULE: SQL statement parser library * * AUTHOR(S): lex.l and yac.y were originally 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. * *****************************************************************************/ #include #include #include #include #include #include SQLPSTMT *sqlpStmt; /* 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 "?"; }