b3a34c696d317da9ab87bd11f71e979181bd638c
kent
  Mon Oct 8 15:52:31 2018 -0700
Adding support for + - * / as mathematical binary expressions.  Also making fields with undefined values act as zeroes when an integer is expected.  Also making from, where, and, or etc. not case sensitive.

diff --git src/lib/rqlEval.c src/lib/rqlEval.c
index 7d7e2ef..84feb57 100644
--- src/lib/rqlEval.c
+++ src/lib/rqlEval.c
@@ -129,30 +129,136 @@
 	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;
 }
 
+static struct rqlEval rqlEvalAdd(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+	struct lm *lm)
+/* Return a + b. */
+{
+struct rqlParse *lp = p->children;
+struct rqlParse *rp = lp->next;
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
+struct rqlEval res;
+switch (lv.type)
+    {
+    case rqlTypeInt:
+	res.val.i = (lv.val.i + rv.val.i);
+	break;
+    case rqlTypeDouble:
+	res.val.x = (lv.val.x + rv.val.x);
+	break;
+    default:
+	internalErr();
+	res.val.b = FALSE;
+	break;
+    }
+res.type = lv.type;
+return res;
+}
+
+static struct rqlEval rqlEvalSubtract(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+	struct lm *lm)
+/* Return a - b. */
+{
+struct rqlParse *lp = p->children;
+struct rqlParse *rp = lp->next;
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
+struct rqlEval res;
+switch (lv.type)
+    {
+    case rqlTypeInt:
+	res.val.i = (lv.val.i - rv.val.i);
+	break;
+    case rqlTypeDouble:
+	res.val.x = (lv.val.x - rv.val.x);
+	break;
+    default:
+	internalErr();
+	res.val.b = FALSE;
+	break;
+    }
+res.type = lv.type;
+return res;
+}
+
+static struct rqlEval rqlEvalMultiply(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+	struct lm *lm)
+/* Return a * b. */
+{
+struct rqlParse *lp = p->children;
+struct rqlParse *rp = lp->next;
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
+struct rqlEval res;
+switch (lv.type)
+    {
+    case rqlTypeInt:
+	res.val.i = (lv.val.i * rv.val.i);
+	break;
+    case rqlTypeDouble:
+	res.val.x = (lv.val.x * rv.val.x);
+	break;
+    default:
+	internalErr();
+	res.val.b = FALSE;
+	break;
+    }
+res.type = lv.type;
+return res;
+}
+
+static struct rqlEval rqlEvalDivide(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+	struct lm *lm)
+/* Return a / b. */
+{
+struct rqlParse *lp = p->children;
+struct rqlParse *rp = lp->next;
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
+struct rqlEval res;
+switch (lv.type)
+    {
+    case rqlTypeInt:
+	res.val.i = (lv.val.i / rv.val.i);
+	break;
+    case rqlTypeDouble:
+	res.val.x = (lv.val.x / rv.val.x);
+	break;
+    default:
+	internalErr();
+	res.val.b = FALSE;
+	break;
+    }
+res.type = lv.type;
+return res;
+}
+
+
+
 static struct rqlEval rqlEvalLike(struct rqlParse *p, void *record, RqlEvalLookup lookup,
 	struct lm *lm)
 /* Return true if r like l . */
 {
 struct rqlParse *lp = p->children;
 struct rqlParse *rp = lp->next;
 struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
 struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
 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;
 }
@@ -262,32 +368,30 @@
 	res.type = rqlTypeBoolean;
 	res.val.b = (res.val.s[0] != 0);
 	break;
     case rqlOpIntToBoolean:
         res = rqlLocalEval(p->children, record, lookup, lm);
 	res.type = rqlTypeBoolean;
 	res.val.b = (res.val.i != 0);
 	break;
     case rqlOpDoubleToBoolean:
         res = rqlLocalEval(p->children, record, lookup, lm);
 	res.type = rqlTypeBoolean;
 	res.val.b = (res.val.x != 0.0);
 	break;
     case rqlOpStringToInt:
 	res = rqlLocalEval(p->children, record, lookup, lm);
-	if (isEmpty(res.val.s))
-	    errAbort("Expecting an integer value but got undefined symbol.");
 	res.type = rqlTypeInt;
 	res.val.i = atoll(res.val.s);
 	break;
     case rqlOpDoubleToInt:
 	res = rqlLocalEval(p->children, record, lookup, lm);
 	res.type = rqlTypeInt;
 	res.val.i = res.val.x;
 	break;
 
     case rqlOpStringToDouble:
 	res = rqlLocalEval(p->children, record, lookup, lm);
 	res.type = rqlTypeDouble;
 	res.val.x = atof(res.val.s);
 	break;
     case rqlOpBooleanToInt:
@@ -308,30 +412,44 @@
 
     /* Arithmetical negation. */
     case rqlOpUnaryMinusInt:
         res = rqlLocalEval(p->children, record, lookup, lm);
 	res.val.i = -res.val.i;
 	break;
     case rqlOpUnaryMinusDouble:
         res = rqlLocalEval(p->children, record, lookup, lm);
 	res.val.x = -res.val.x;
 	break;
 
     case rqlOpArrayIx:
        res = rqlEvalArrayIx(p, record, lookup, lm);
        break;
 
+    /* Mathematical ops, simple binary type */
+    case rqlOpAdd:
+       res = rqlEvalAdd(p, record, lookup, lm);
+       break;
+    case rqlOpSubtract:
+       res = rqlEvalSubtract(p, record, lookup, lm);
+       break;
+    case rqlOpMultiply:
+       res = rqlEvalMultiply(p, record, lookup, lm);
+       break;
+    case rqlOpDivide:
+       res = rqlEvalDivide(p, record, lookup, lm);
+       break;
+
     default:
         errAbort("Unknown op %s\n", rqlOpToString(p->op));
 	res.type = rqlTypeInt;	// Keep compiler from complaining.
 	res.val.i = 0;	// Keep compiler from complaining.
 	break;
     }
 return res;
 }
 
 struct rqlEval rqlEvalOnRecord(struct rqlParse *p, void *record, RqlEvalLookup lookup, 
 	struct lm *lm)
 /* Evaluate parse tree on record, using lm for memory for string operations. */
 {
 return rqlLocalEval(p, record, lookup, lm);
 }