src/utils/raSqlQuery/raSqlQuery.c 1.4
1.4 2009/11/20 01:52:43 kent
Adding inequalities. Reducing debugging uglies to verboses.
Index: src/utils/raSqlQuery/raSqlQuery.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/utils/raSqlQuery/raSqlQuery.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -b -B -U 4 -r1.3 -r1.4
--- src/utils/raSqlQuery/raSqlQuery.c 20 Nov 2009 01:35:37 -0000 1.3
+++ src/utils/raSqlQuery/raSqlQuery.c 20 Nov 2009 01:52:43 -0000 1.4
@@ -82,8 +82,13 @@
rqlParseIntToDouble,
rqlParseUnaryMinusDouble,
+ rqlParseGt, /* Greater than comparison. */
+ rqlParseLt, /* Less than comparison. */
+ rqlParseGe, /* Greater than or equals comparison. */
+ rqlParseLe, /* Less than or equals comparison. */
+
rqlParseAnd, /* An and */
rqlParseOr, /* An or */
};
@@ -119,8 +124,18 @@
return "rqlParseIntToDouble";
case rqlParseUnaryMinusDouble:
return "rqlParseUnaryMinusDouble";
+
+ case rqlParseGt:
+ return "rqlParseGt";
+ case rqlParseLt:
+ return "rqlParseLt";
+ case rqlParseGe:
+ return "rqlParseGe";
+ case rqlParseLe:
+ return "rqlParseLe";
+
default:
return "rqlParseUnknown";
}
}
@@ -379,8 +394,21 @@
return rqlParseAtom(tkz);
}
}
+boolean eatMatchingTok(struct tokenizer *tkz, char *s)
+/* If next token matches s then eat it and return TRUE */
+{
+char *tok = tokenizerNext(tkz);
+if (tok != NULL && sameString(tok, s))
+ return TRUE;
+else
+ {
+ tokenizerReuse(tkz);
+ return FALSE;
+ }
+}
+
struct rqlParse *rqlParseCmp(struct tokenizer *tkz)
/* Parse out comparison. */
{
struct rqlParse *l = rqlParseUnaryMinus(tkz);
@@ -397,8 +425,22 @@
{
op = rqlParseNe;
skipOverRequired(tkz, "=");
}
+ else if (sameString(tok, ">"))
+ {
+ if (eatMatchingTok(tkz, "="))
+ op = rqlParseGe;
+ else
+ op = rqlParseGt;
+ }
+ else if (sameString(tok, "<"))
+ {
+ if (eatMatchingTok(tkz, "="))
+ op = rqlParseGe;
+ else
+ op = rqlParseLe;
+ }
else
{
tokenizerReuse(tkz);
return p;
@@ -492,10 +534,8 @@
struct rqlParse *lp = p->children;
struct rqlParse *rp = lp->next;
struct rqlEval lv = rqlEvalOnRecord(lp, ra);
struct rqlEval rv = rqlEvalOnRecord(rp, ra);
-if (lv.type != rv.type)
- errAbort("Mixed types in rqlParseEquals");
struct rqlEval res;
res.type = rqlTypeBoolean;
switch (lv.type)
{
@@ -511,10 +551,73 @@
case rqlTypeDouble:
res.val.b = (lv.val.x == rv.val.x);
break;
default:
- errAbort("Unknown type %d", lv.type);
+ internalErr();
res.val.b = FALSE;
+ break;
+ }
+return res;
+}
+
+struct rqlEval rqlEvalLt(struct rqlParse *p, struct raRecord *ra)
+/* Return true if r < 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;
+switch (lv.type)
+ {
+ case rqlTypeBoolean:
+ res.val.b = (lv.val.b < rv.val.b);
+ break;
+ case rqlTypeString:
+ res.val.b = strcmp(lv.val.s, rv.val.s) < 0;
+ break;
+ case rqlTypeInt:
+ res.val.b = (lv.val.i < rv.val.i);
+ break;
+ case rqlTypeDouble:
+ res.val.b = (lv.val.x < rv.val.x);
+ break;
+ default:
+ internalErr();
+ res.val.b = FALSE;
+ break;
+ }
+return res;
+}
+
+struct rqlEval rqlEvalGt(struct rqlParse *p, struct raRecord *ra)
+/* Return true if r > 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;
+switch (lv.type)
+ {
+ case rqlTypeBoolean:
+ res.val.b = (lv.val.b > rv.val.b);
+ break;
+ case rqlTypeString:
+ res.val.b = strcmp(lv.val.s, rv.val.s) > 0;
+ break;
+ case rqlTypeInt:
+ res.val.b = (lv.val.i > rv.val.i);
+ break;
+ case rqlTypeDouble:
+ res.val.b = (lv.val.x > rv.val.x);
+ break;
+ default:
+ internalErr();
+ res.val.b = FALSE;
+ break;
}
return res;
}
@@ -543,8 +646,24 @@
res = rqlEvalEq(p, ra);
res.val.b = !res.val.b;
break;
+ /* Inequalities. */
+ case rqlParseLt:
+ res = rqlEvalLt(p, ra);
+ break;
+ case rqlParseGt:
+ res = rqlEvalGt(p, ra);
+ break;
+ case rqlParseLe:
+ res = rqlEvalGt(p, ra);
+ res.val.b = !res.val.b;
+ break;
+ case rqlParseGe:
+ res = rqlEvalLt(p, ra);
+ res.val.b = !res.val.b;
+ break;
+
/* Type casts. */
case rqlParseStringToBoolean:
res = rqlEvalOnRecord(p->children, ra);
res.type = rqlTypeBoolean;
@@ -756,11 +875,12 @@
FILE *out)
/* raSqlQuery - Do a SQL-like query on a RA file.. */
{
struct raRecord *raList = readRaRecords(inCount, inNames, mergeField, lm);
-uglyf("Got %d ra records\n", slCount(raList));
struct rqlStatement *rql = rqlStatementParse(query);
-rqlStatementDump(rql, uglyOut);
+verbose(2, "Got %d records in raFiles\n", slCount(raList));
+if (verboseLevel() > 1)
+ rqlStatementDump(rql, stderr);
struct raRecord *ra;
int matchCount = 0;
boolean doSelect = sameString(rql->command, "select");
for (ra = raList; ra != NULL; ra = ra->next)