From 3bdb92524be3710622e1a9ed2be4f8a0ec9b7a61 Mon Sep 17 00:00:00 2001 From: alexhudson Date: Thu, 24 Jun 2010 19:54:25 +0000 Subject: [PATCH] Pretty ropey initial support for a '^' BQL operator that behaves like LIKE. --- src/agents/store/query-builder.c | 24 ++++++++++++++++++++++-- src/agents/store/query-parser.c | 19 ++++++++++++++++++- src/agents/store/query-parser.h | 1 + 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/agents/store/query-builder.c b/src/agents/store/query-builder.c index 476cdfd..4623360 100644 --- a/src/agents/store/query-builder.c +++ b/src/agents/store/query-builder.c @@ -423,6 +423,7 @@ QueryBuilderCreateSQL(QueryBuilder *builder, char **output) BongoStringBuilderAppend(&b, ";"); *output = MemStrdup(b.value); + printf("SQL: '%s'\n", b.value); BongoStringBuilderDestroy(&b); @@ -476,7 +477,7 @@ AddExpValueByProperty(QueryBuilder *b, BongoStringBuilder *sb, void *exp, int co static int QueryExpressionToSQL(QueryBuilder *builder, struct expression *exp, BongoStringBuilder *sb) { - const char basic_ops[] = "&|<>=!~"; + const char basic_ops[] = "&|<>=!~^"; int retcode = 0; for (unsigned int i=0; i < sizeof(basic_ops); i++) { @@ -504,12 +505,31 @@ QueryExpressionToSQL(QueryBuilder *builder, struct expression *exp, BongoStringB case '!': BongoStringBuilderAppend(sb, " != "); break; + case '^': + BongoStringBuilderAppend(sb, " LIKE "); + break; default: // return 0; break; } - retcode = AddExpValueByProperty(builder, sb, exp->exp2, exp->exp2_const); + char *val = exp->exp2; + if (exp->op[0] == '^') { + // special case for LIKE: we need to stick % on the param + int len = strlen(exp->exp2); + val = malloc(len + 4); + val[0] = '\''; val[1] = '%'; + char *expression = (char*)exp->exp2; + for(int i=1; i < len; i++) val[i+1] = expression[i]; + val[len] = '%'; + val[len+1] = '\''; + val[len+2] = '\0'; + } + + retcode = AddExpValueByProperty(builder, sb, val, exp->exp2_const); + + if (val != exp->exp2) free(val); + if (retcode) return retcode; BongoStringBuilderAppend(sb, ")"); diff --git a/src/agents/store/query-parser.c b/src/agents/store/query-parser.c index fa01502..42a8ff3 100644 --- a/src/agents/store/query-parser.c +++ b/src/agents/store/query-parser.c @@ -76,7 +76,7 @@ pull_token(char **query, char **out_token) int QueryParser_IsOp (const char *token) { - const char *ops = "&|<>=!{l~"; + const char *ops = "&|<>=!{l~^"; // operations must be single characters if (token[1] != '\0') return -1; @@ -88,6 +88,16 @@ QueryParser_IsOp (const char *token) return -1; } +int +QueryParser_CanSubExp (const char *token) +{ + // this is true for any operator that can take sub-expressions. + // basically just the boolean operators. + if (token[0] == '&') return 0; + if (token[0] == '|') return 0; + return -1; +} + #define CHAR_IS_LC_ALPHA(x) (((x) >= 'a') && ((x) <= 'z')) #define CHAR_IS_NUMBER(x) (((x) >= '0') && ((x) <= '9')) #define CHAR_IS_PERIOD(x) ((x) == '.') @@ -194,6 +204,13 @@ QueryParserRun(struct parser_state *state, BOOL strict_quotes) } if (QueryParser_IsOp(token) == 0) { if (current_expression->op != NULL) { + // check this operator will allow sub-expressions + // TODO - this isn't quite right yet. + //if (QueryParser_CanSubExp(current_expression->op) == 0) { + // DEBUG_MESSAGE("ERR: Cannot accept subexpression at this point\n"); + // return -1; + //} + // need to find a free expr slot struct expression *next_expression = ++(state->last); diff --git a/src/agents/store/query-parser.h b/src/agents/store/query-parser.h index e928f14..9cf9665 100644 --- a/src/agents/store/query-parser.h +++ b/src/agents/store/query-parser.h @@ -32,6 +32,7 @@ int QueryParserRun(struct parser_state *state, BOOL strict_quotes); void QueryParserFinish(struct parser_state *state); int QueryParser_IsOp (const char *token); +int QueryParser_CanSubExp (const char *token); int QueryParser_IsProperty (const char *token); int QueryParser_IsNumber (const char *token); int QueryParser_IsString (const char *token);