src/utils/raSqlQuery/raSqlQuery.c 1.7

1.7 2009/11/20 06:00:29 kent
Adding 'or' and 'and'
Index: src/utils/raSqlQuery/raSqlQuery.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/utils/raSqlQuery/raSqlQuery.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -b -B -U 4 -r1.6 -r1.7
--- src/utils/raSqlQuery/raSqlQuery.c	20 Nov 2009 04:57:14 -0000	1.6
+++ src/utils/raSqlQuery/raSqlQuery.c	20 Nov 2009 06:00:29 -0000	1.7
@@ -75,8 +75,10 @@
     rqlParseEq,	/* An equals comparison */
     rqlParseNe,	/* A not equals comparison */
 
     rqlParseStringToBoolean,
+    rqlParseIntToBoolean,
+    rqlParseDoubleToBoolean,
     rqlParseStringToInt,
     rqlParseStringToDouble,
     rqlParseBooleanToInt,
     rqlParseBooleanToDouble,
@@ -113,8 +115,12 @@
 	return "rqlParseOr";
     
     case rqlParseStringToBoolean:
         return "rqlParseStringToBoolean";
+    case rqlParseIntToBoolean:
+        return "rqlParseIntToBoolean";
+    case rqlParseDoubleToBoolean:
+        return "rqlParseDoubleToBoolean";
     case rqlParseStringToInt:
         return "rqlParseStringToInt";
     case rqlParseStringToDouble:
         return "rqlParseStringToDouble";
@@ -307,8 +313,12 @@
 switch (oldType)
     {
     case rqlTypeString:
         return rqlParseStringToBoolean;
+    case rqlTypeInt:
+        return rqlParseIntToBoolean;
+    case rqlTypeDouble:
+        return rqlParseDoubleToBoolean;
     default:
         internalErr();
 	return rqlParseUnknown;
     }
@@ -482,12 +492,72 @@
     }
 return p;
 }
 
+struct rqlParse *rqlParseAndLoop(struct tokenizer *tkz)
+/* Parse out and or or. */
+{
+struct rqlParse *l = rqlParseCoerce(rqlParseCmp(tkz), rqlTypeBoolean);
+struct rqlParse *parent = NULL;
+struct rqlParse *p = l;
+for (;;)
+    {
+    char *tok = tokenizerNext(tkz);
+    if (tok == NULL || !sameString(tok, "and"))
+        {
+	tokenizerReuse(tkz);
+	return p;
+	}
+    else
+        {
+	if (parent == NULL)
+	    {
+	    AllocVar(parent);
+	    parent->op = rqlParseAnd;
+	    parent->type = rqlTypeBoolean;
+	    parent->children = p;
+	    p = parent;
+	    }
+	struct rqlParse *r = rqlParseCoerce(rqlParseCmp(tkz), rqlTypeBoolean);
+	slAddTail(&parent->children, r);
+	}
+    }
+}
+
+struct rqlParse *rqlParseOrLoop(struct tokenizer *tkz)
+/* Parse out and or or. */
+{
+struct rqlParse *l = rqlParseCoerce(rqlParseAndLoop(tkz), rqlTypeBoolean);
+struct rqlParse *parent = NULL;
+struct rqlParse *p = l;
+for (;;)
+    {
+    char *tok = tokenizerNext(tkz);
+    if (tok == NULL || !sameString(tok, "or"))
+        {
+	tokenizerReuse(tkz);
+	return p;
+	}
+    else
+        {
+	if (parent == NULL)
+	    {
+	    AllocVar(parent);
+	    parent->op = rqlParseOr;
+	    parent->type = rqlTypeBoolean;
+	    parent->children = p;
+	    p = parent;
+	    }
+	struct rqlParse *r = rqlParseCoerce(rqlParseAndLoop(tkz), rqlTypeBoolean);
+	slAddTail(&parent->children, r);
+	}
+    }
+}
+
 struct rqlParse *rqlParseClause(struct tokenizer *tkz)
 /* Parse out a clause, usually a where clause. */
 {
-return rqlParseCmp(tkz);
+return rqlParseOrLoop(tkz);
 }
 
 char *rqlParseFieldSpec(struct tokenizer *tkz, struct dyString *buf)
 /* Return a field spec, which may contain * and ?. Put results in buf, and 
@@ -740,14 +810,58 @@
     case rqlParseLike:
         res = rqlEvalLike(p,ra);
 	break;
 
+    /* Logical ops. */
+    case rqlParseAnd:
+	{
+        res.type = rqlTypeBoolean;
+	res.val.b = TRUE;
+	struct rqlParse *c;
+	for (c = p->children; c != NULL; c= c->next)
+	    {
+	    struct rqlEval e = rqlEvalOnRecord(c, ra);
+	    if (!e.val.b)
+		{
+	        res.val.b = FALSE;
+		break;
+		}
+	    }
+	break;
+	}
+    case rqlParseOr:
+	{
+        res.type = rqlTypeBoolean;
+	res.val.b = FALSE;
+	struct rqlParse *c;
+	for (c = p->children; c != NULL; c= c->next)
+	    {
+	    struct rqlEval e = rqlEvalOnRecord(c, ra);
+	    if (e.val.b)
+		{
+	        res.val.b = TRUE;
+		break;
+		}
+	    }
+	break;
+	}
+
     /* Type casts. */
     case rqlParseStringToBoolean:
 	res = rqlEvalOnRecord(p->children, ra);
 	res.type = rqlTypeBoolean;
 	res.val.b = (res.val.s[0] != 0);
 	break;
+    case rqlParseIntToBoolean:
+        res = rqlEvalOnRecord(p->children, ra);
+	res.type = rqlTypeBoolean;
+	res.val.b = (res.val.i != 0);
+	break;
+    case rqlParseDoubleToBoolean:
+        res = rqlEvalOnRecord(p->children, ra);
+	res.type = rqlTypeBoolean;
+	res.val.b = (res.val.x != 0.0);
+	break;
     case rqlParseStringToInt:
 	res = rqlEvalOnRecord(p->children, ra);
 	res.type = rqlTypeInt;
 	res.val.i = atoi(res.val.s);