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)