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); }