src/utils/raSqlQuery/raSqlQuery.c 1.6
1.6 2009/11/20 04:57:14 kent
Allowing like in where spec.
Index: src/utils/raSqlQuery/raSqlQuery.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/utils/raSqlQuery/raSqlQuery.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -b -B -U 4 -r1.5 -r1.6
--- src/utils/raSqlQuery/raSqlQuery.c 20 Nov 2009 04:39:16 -0000 1.5
+++ src/utils/raSqlQuery/raSqlQuery.c 20 Nov 2009 04:57:14 -0000 1.6
@@ -87,8 +87,9 @@
rqlParseGt, /* Greater than comparison. */
rqlParseLt, /* Less than comparison. */
rqlParseGe, /* Greater than or equals comparison. */
rqlParseLe, /* Less than or equals comparison. */
+ rqlParseLike, /* SQL wildcard compare. */
rqlParseAnd, /* An and */
rqlParseOr, /* An or */
};
@@ -134,8 +135,10 @@
case rqlParseGe:
return "rqlParseGe";
case rqlParseLe:
return "rqlParseLe";
+ case rqlParseLike:
+ return "rqlParseLike";
default:
return "rqlParseUnknown";
}
@@ -414,8 +417,9 @@
{
struct rqlParse *l = rqlParseUnaryMinus(tkz);
struct rqlParse *p = l;
char *tok = tokenizerNext(tkz);
+boolean forceString = FALSE;
if (tok != NULL)
{
enum rqlParseOp op = rqlParseUnknown;
if (sameString(tok, "="))
@@ -440,8 +444,13 @@
op = rqlParseGe;
else
op = rqlParseLe;
}
+ else if (sameString(tok, "like"))
+ {
+ forceString = TRUE;
+ op = rqlParseLike;
+ }
else
{
tokenizerReuse(tkz);
return p;
@@ -451,11 +460,22 @@
p->op = op;
p->type = rqlTypeBoolean;
/* Now force children to be the same type, inserting casts if need be. */
+ if (forceString)
+ {
+ if (l->type != rqlTypeString || r->type != rqlTypeString)
+ {
+ errAbort("Expecting string type around comparison line %d of %s",
+ tkz->lf->lineIx, tkz->lf->fileName);
+ }
+ }
+ else
+ {
enum rqlType childType = commonTypeForBop(l->type, r->type);
l = rqlParseCoerce(l, childType);
r = rqlParseCoerce(r, childType);
+ }
/* Now hang children onto node. */
p->children = l;
l->next = r;
@@ -660,8 +680,23 @@
}
return res;
}
+struct rqlEval rqlEvalLike(struct rqlParse *p, struct raRecord *ra)
+/* Return true if r like l . */
+{
+struct rqlParse *lp = p->children;
+struct rqlParse *rp = lp->next;
+struct rqlEval lv = rqlEvalOnRecord(lp, ra);
+struct rqlEval rv = rqlEvalOnRecord(rp, ra);
+struct rqlEval res;
+res.type = rqlTypeBoolean;
+assert(rv.type == rqlTypeString);
+assert(rv.type == lv.type);
+res.val.b = sqlMatchLike(rv.val.s, lv.val.s);
+return res;
+}
+
struct rqlEval rqlEvalOnRecord(struct rqlParse *p, struct raRecord *ra)
/* Evaluate self on ra. */
{
struct rqlEval res;
@@ -701,8 +736,11 @@
case rqlParseGe:
res = rqlEvalLt(p, ra);
res.val.b = !res.val.b;
break;
+ case rqlParseLike:
+ res = rqlEvalLike(p,ra);
+ break;
/* Type casts. */
case rqlParseStringToBoolean:
res = rqlEvalOnRecord(p->children, ra);