src/lib/rqlEval.c 1.3
1.3 2009/12/03 19:26:04 kent
Making rqlParser handle arrays and field-separating-dots. Evaluation handles arrays but not dots yet.
Index: src/lib/rqlEval.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/rqlEval.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -b -B -U 4 -r1.2 -r1.3
--- src/lib/rqlEval.c 3 Dec 2009 18:19:28 -0000 1.2
+++ src/lib/rqlEval.c 3 Dec 2009 19:26:04 -0000 1.3
@@ -4,14 +4,18 @@
#include "common.h"
#include "linefile.h"
#include "hash.h"
#include "dystring.h"
+#include "localmem.h"
#include "tokenizer.h"
#include "sqlNum.h"
#include "rql.h"
static char const rcsid[] = "$Id$";
+struct rqlEval rqlLocalEval(struct rqlParse *p, void *record, RqlEvalLookup lookup, struct lm *lm);
+/* Evaluate self on parse tree, allocating memory if needed from lm. */
+
struct rqlEval rqlEvalCoerceToBoolean(struct rqlEval r)
/* Return TRUE if it's a nonempty string or a non-zero number. */
{
switch (r.type)
@@ -35,16 +39,17 @@
r.type = rqlTypeBoolean;
return r;
}
-static struct rqlEval rqlEvalEq(struct rqlParse *p, void *record, RqlEvalLookup lookup)
+static struct rqlEval rqlEvalEq(struct rqlParse *p,
+ void *record, RqlEvalLookup lookup, struct lm *lm)
/* Return true if two children are equal regardless of children type
* (which are just gauranteed to be the same). */
{
struct rqlParse *lp = p->children;
struct rqlParse *rp = lp->next;
-struct rqlEval lv = rqlEvalOnRecord(lp, record, lookup);
-struct rqlEval rv = rqlEvalOnRecord(rp, record, lookup);
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
struct rqlEval res;
res.type = rqlTypeBoolean;
assert(lv.type == rv.type);
switch (lv.type)
@@ -68,15 +73,16 @@
}
return res;
}
-static struct rqlEval rqlEvalLt(struct rqlParse *p, void *record, RqlEvalLookup lookup)
+static struct rqlEval rqlEvalLt(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+ struct lm *lm)
/* Return true if r < l . */
{
struct rqlParse *lp = p->children;
struct rqlParse *rp = lp->next;
-struct rqlEval lv = rqlEvalOnRecord(lp, record, lookup);
-struct rqlEval rv = rqlEvalOnRecord(rp, record, lookup);
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
struct rqlEval res;
res.type = rqlTypeBoolean;
switch (lv.type)
{
@@ -99,15 +105,16 @@
}
return res;
}
-static struct rqlEval rqlEvalGt(struct rqlParse *p, void *record, RqlEvalLookup lookup)
+static struct rqlEval rqlEvalGt(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+ struct lm *lm)
/* Return true if r > l . */
{
struct rqlParse *lp = p->children;
struct rqlParse *rp = lp->next;
-struct rqlEval lv = rqlEvalOnRecord(lp, record, lookup);
-struct rqlEval rv = rqlEvalOnRecord(rp, record, lookup);
+struct rqlEval lv = rqlLocalEval(lp, record, lookup, lm);
+struct rqlEval rv = rqlLocalEval(rp, record, lookup, lm);
struct rqlEval res;
res.type = rqlTypeBoolean;
switch (lv.type)
{
@@ -130,25 +137,57 @@
}
return res;
}
-static struct rqlEval rqlEvalLike(struct rqlParse *p, void *record, RqlEvalLookup lookup)
+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 = rqlEvalOnRecord(lp, record, lookup);
-struct rqlEval rv = rqlEvalOnRecord(rp, record, lookup);
+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;
}
-struct rqlEval rqlEvalOnRecord(struct rqlParse *p, void *record, RqlEvalLookup lookup)
-/* Evaluate self on ra. */
+char *lmCloneSomeWord(struct lm *lm, char *line, int wordIx)
+/* Return a clone of the given space-delimited word within line. Returns NULL if
+ * not that many words in line. */
+{
+if (wordIx < 0)
+ return NULL;
+int i;
+for (i=0; i<wordIx; ++i)
+ {
+ line = skipLeadingSpaces(line);
+ line = skipToSpaces(line);
+ if (line == NULL)
+ return NULL;
+ }
+return lmCloneFirstWord(lm, line);
+}
+
+static struct rqlEval rqlEvalArrayIx(struct rqlParse *p, void *record, RqlEvalLookup lookup,
+ struct lm *lm)
+/* Handle parse tree generated by an indexed array. */
+{
+struct rqlParse *array = p->children;
+struct rqlParse *index = array->next;
+struct rqlEval arrayVal = rqlLocalEval(array, record, lookup, lm);
+struct rqlEval indexVal = rqlLocalEval(index, record, lookup, lm);
+struct rqlEval res;
+res.type = rqlTypeString;
+res.val.s = emptyForNull(lmCloneSomeWord(lm, arrayVal.val.s, indexVal.val.i));
+return res;
+}
+
+struct rqlEval rqlLocalEval(struct rqlParse *p, void *record, RqlEvalLookup lookup, struct lm *lm)
+/* Evaluate self on parse tree, allocating memory if needed from lm. */
{
struct rqlEval res;
switch (p->op)
{
@@ -164,32 +203,32 @@
else
res.val.s = s;
break;
case rqlOpEq:
- res = rqlEvalEq(p, record, lookup);
+ res = rqlEvalEq(p, record, lookup, lm);
break;
case rqlOpNe:
- res = rqlEvalEq(p, record, lookup);
+ res = rqlEvalEq(p, record, lookup, lm);
res.val.b = !res.val.b;
break;
/* Inequalities. */
case rqlOpLt:
- res = rqlEvalLt(p, record, lookup);
+ res = rqlEvalLt(p, record, lookup, lm);
break;
case rqlOpGt:
- res = rqlEvalGt(p, record, lookup);
+ res = rqlEvalGt(p, record, lookup, lm);
break;
case rqlOpLe:
- res = rqlEvalGt(p, record, lookup);
+ res = rqlEvalGt(p, record, lookup, lm);
res.val.b = !res.val.b;
break;
case rqlOpGe:
- res = rqlEvalLt(p, record, lookup);
+ res = rqlEvalLt(p, record, lookup, lm);
res.val.b = !res.val.b;
break;
case rqlOpLike:
- res = rqlEvalLike(p,record, lookup);
+ res = rqlEvalLike(p,record, lookup, lm);
break;
/* Logical ops. */
case rqlOpAnd:
@@ -198,9 +237,9 @@
res.val.b = TRUE;
struct rqlParse *c;
for (c = p->children; c != NULL; c= c->next)
{
- struct rqlEval e = rqlEvalOnRecord(c, record, lookup);
+ struct rqlEval e = rqlLocalEval(c, record, lookup, lm);
if (!e.val.b)
{
res.val.b = FALSE;
break;
@@ -214,9 +253,9 @@
res.val.b = FALSE;
struct rqlParse *c;
for (c = p->children; c != NULL; c= c->next)
{
- struct rqlEval e = rqlEvalOnRecord(c, record, lookup);
+ struct rqlEval e = rqlLocalEval(c, record, lookup, lm);
if (e.val.b)
{
res.val.b = TRUE;
break;
@@ -225,64 +264,74 @@
break;
}
case rqlOpNot:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.val.b = !res.val.b;
break;
/* Type casts. */
case rqlOpStringToBoolean:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeBoolean;
res.val.b = (res.val.s[0] != 0);
break;
case rqlOpIntToBoolean:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeBoolean;
res.val.b = (res.val.i != 0);
break;
case rqlOpDoubleToBoolean:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeBoolean;
res.val.b = (res.val.x != 0.0);
break;
case rqlOpStringToInt:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeInt;
res.val.i = atoi(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 = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeDouble;
res.val.x = atof(res.val.s);
break;
case rqlOpBooleanToInt:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeInt;
res.val.i = res.val.b;
break;
case rqlOpBooleanToDouble:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeDouble;
res.val.x = res.val.b;
break;
case rqlOpIntToDouble:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.type = rqlTypeDouble;
res.val.x = res.val.b;
break;
/* Arithmetical negation. */
case rqlOpUnaryMinusInt:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.val.i = -res.val.i;
break;
case rqlOpUnaryMinusDouble:
- res = rqlEvalOnRecord(p->children, record, lookup);
+ res = rqlLocalEval(p->children, record, lookup, lm);
res.val.x = -res.val.x;
break;
+ case rqlOpArrayIx:
+ res = rqlEvalArrayIx(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.
@@ -290,4 +339,12 @@
}
return res;
}
+struct rqlEval rqlEvalOnRecord(struct rqlParse *p, void *record, RqlEvalLookup lookup)
+/* Evaluate self on record. */
+{
+struct lm *lm = lmInit(0);
+struct rqlEval res = rqlLocalEval(p, record, lookup, lm);
+lmCleanup(&lm);
+return res;
+}