Changeset: de68ac6da8a2 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=de68ac6da8a2 Modified Files: monetdb5/extras/jaql/Tests/All monetdb5/extras/jaql/Tests/filter01.stable.err monetdb5/extras/jaql/Tests/filter01.stable.out monetdb5/extras/jaql/jaql.c monetdb5/extras/jaql/jaqlgencode.c Branch: jacqueline Log Message:
filter: implemented complex conditionals (and boolean ones) allow to combine conditionals with and/or allow boolean matching this makes filter01 (examples from the docs) run diffs (truncated from 562 to 300 lines): diff --git a/monetdb5/extras/jaql/Tests/All b/monetdb5/extras/jaql/Tests/All --- a/monetdb5/extras/jaql/Tests/All +++ b/monetdb5/extras/jaql/Tests/All @@ -7,8 +7,7 @@ variable00 plan00 # examples from the docs -#fail until we implement combined predicates -#filter01 +filter01 transform01 #fail until we solve the syntactic mess of expand #expand01 diff --git a/monetdb5/extras/jaql/Tests/filter01.stable.err b/monetdb5/extras/jaql/Tests/filter01.stable.err new file mode 100644 --- /dev/null +++ b/monetdb5/extras/jaql/Tests/filter01.stable.err @@ -0,0 +1,31 @@ +stderr of test 'filter01` in directory 'extras/jaql` itself: + + +# 16:55:59 > +# 16:55:59 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "gdk_dbfarm=/net/sofia.ins.cwi.nl/export/scratch1/fabian/tmp/mtest-jacqueline-sofia.ins.cwi.nl/five/dbfarm" "--set" "mapi_open=true" "--set" "mapi_port=34179" "--set" "monet_prompt=" "--trace" "--forcemito" "--set" "mal_listing=2" "--dbname=mTests_extras_jaql" "filter01.mal" +# 16:55:59 > + +# builtin opt gdk_dbname = demo +# builtin opt gdk_dbfarm = /ufs/fabian/scratch/ssd/monetdb/jacqueline/program-x86_64/var/lib/monetdb5/dbfarm +# builtin opt gdk_debug = 0 +# builtin opt gdk_alloc_map = no +# builtin opt gdk_vmtrim = yes +# builtin opt monet_prompt = > +# builtin opt monet_daemon = no +# builtin opt mapi_port = 50000 +# builtin opt mapi_open = false +# builtin opt mapi_autosense = false +# builtin opt sql_optimizer = default_pipe +# builtin opt sql_debug = 0 +# cmdline opt gdk_nr_threads = 0 +# cmdline opt gdk_dbfarm = /net/sofia.ins.cwi.nl/export/scratch1/fabian/tmp/mtest-jacqueline-sofia.ins.cwi.nl/five/dbfarm +# cmdline opt mapi_open = true +# cmdline opt mapi_port = 34179 +# cmdline opt monet_prompt = +# cmdline opt mal_listing = 2 +# cmdline opt gdk_dbname = mTests_extras_jaql + +# 16:55:59 > +# 16:55:59 > "Done." +# 16:55:59 > + diff --git a/monetdb5/extras/jaql/Tests/filter01.stable.out b/monetdb5/extras/jaql/Tests/filter01.stable.out new file mode 100644 --- /dev/null +++ b/monetdb5/extras/jaql/Tests/filter01.stable.out @@ -0,0 +1,33 @@ +stdout of test 'filter01` in directory 'extras/jaql` itself: + + +# 16:55:59 > +# 16:55:59 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "gdk_dbfarm=/net/sofia.ins.cwi.nl/export/scratch1/fabian/tmp/mtest-jacqueline-sofia.ins.cwi.nl/five/dbfarm" "--set" "mapi_open=true" "--set" "mapi_port=34179" "--set" "monet_prompt=" "--trace" "--forcemito" "--set" "mal_listing=2" "--dbname=mTests_extras_jaql" "filter01.mal" +# 16:55:59 > + +# MonetDB 5 server v11.8.0 "jacqueline-497cf791babb+" +# Serving database 'mTests_extras_jaql', using 8 threads +# Compiled for x86_64-pc-linux-gnu/64bit with 64bit OIDs dynamically linked +# Found 15.662 GiB available main-memory. +# Copyright (c) 1993-July 2008 CWI. +# Copyright (c) August 2008-2012 MonetDB B.V., all rights reserved +# Visit http://www.monetdb.org/ for further information +# Listening for connection requests on mapi:monetdb://sofia.ins.cwi.nl:34179/ +# MonetDB/GIS module loaded +# MonetDB/SQL module loaded +# MonetDB/DataCell module not loaded: MALException:jaql.context:JAQL environment not found +function user.main():void; +# from the docs + jaql.x("employees = [{\"name\": \"Jon Doe\", \"income\": 20000, \"mgr\": false}, {\"name\": \"Vince Wayne\", \"income\": 32500, \"mgr\": false}, {\"name\": \"Jane Dean\", \"income\": 72000, \"mgr\": true}, {\"name\": \"Alex Smith\", \"income\": 25000, \"mgr\": false} ];"); + jaql.x("employees -> filter $.mgr or $.income > 30000;"); + jaql.x("employees -> filter each emp emp.mgr or emp.income > 30000;"); + jaql.x("employees -> filter each emp (emp.mgr or emp.income > 30000);"); +end main; +[ { "name": "Vince Wayne", "income": 32500, "mgr": false }, { "name": "Jane Dean", "income": 72000, "mgr": true } ] +[ { "name": "Vince Wayne", "income": 32500, "mgr": false }, { "name": "Jane Dean", "income": 72000, "mgr": true } ] +[ { "name": "Vince Wayne", "income": 32500, "mgr": false }, { "name": "Jane Dean", "income": 72000, "mgr": true } ] + +# 16:55:59 > +# 16:55:59 > "Done." +# 16:55:59 > + diff --git a/monetdb5/extras/jaql/jaql.c b/monetdb5/extras/jaql/jaql.c --- a/monetdb5/extras/jaql/jaql.c +++ b/monetdb5/extras/jaql/jaql.c @@ -124,23 +124,9 @@ append_jaql_pipe(tree *oaction, tree *na return oaction; } -/* create filter action looping over the input array as ident, - * performing pred condition to include each element in the array. */ -tree * -make_jaql_filter(tree *var, tree *pred) -{ - tree *res = GDKzalloc(sizeof(tree)); - res->type = j_filter; - res->tval1 = var; - res->tval2 = pred; - /* FIXME: check pred's var usage, like _check_exp_var */ - - return res; -} - /* recursive helper to check variable usages for validity */ static tree * -_check_exp_var(char *var, tree *t) +_check_exp_var(const char *func, const char *var, tree *t) { tree *res = NULL; @@ -151,24 +137,55 @@ _check_exp_var(char *var, tree *t) if (strcmp(var, t->sval) != 0) { char buf[128]; res = GDKzalloc(sizeof(tree)); - snprintf(buf, sizeof(buf), "transform: unknown variable: %s", - t->sval); + snprintf(buf, sizeof(buf), "%s: unknown variable: %s", + func, t->sval); res->type = j_error; res->sval = GDKstrdup(buf); } return res; } - if ((res = _check_exp_var(var, t->tval1)) != NULL) + if ((res = _check_exp_var(func, var, t->tval1)) != NULL) return res; - if ((res = _check_exp_var(var, t->tval2)) != NULL) + if ((res = _check_exp_var(func, var, t->tval2)) != NULL) return res; - if ((res = _check_exp_var(var, t->tval3)) != NULL) + if ((res = _check_exp_var(func, var, t->tval3)) != NULL) return res; return res; } +/* create filter action looping over the input array as ident, + * performing pred condition to include each element in the array. */ +tree * +make_jaql_filter(tree *var, tree *pred) +{ + tree *res; + + assert(var != NULL && var->type == j_var); + assert(pred != NULL); + + if (pred->type == j_error) { + freetree(var); + return pred; + } + + assert(pred->type == j_pred); + + if ((res = _check_exp_var("filter", var->sval, pred)) != NULL) { + freetree(var); + freetree(pred); + return res; + } + + res = GDKzalloc(sizeof(tree)); + res->type = j_filter; + res->tval1 = var; + res->tval2 = pred; + + return res; +} + /* create transform action looping over the input array as ident, * producing an array with elements mapped from the given template. */ tree * @@ -186,7 +203,7 @@ make_jaql_transform(tree *var, tree *tmp /* traverse down tmpl, searching for all variable references to * check if they refer to var */ - if ((res = _check_exp_var(var->sval, tmpl)) != NULL) { + if ((res = _check_exp_var("transform", var->sval, tmpl)) != NULL) { freetree(var); freetree(tmpl); return res; @@ -296,21 +313,44 @@ make_pred(tree *l, tree *comp, tree *r) { tree *res; + if (l != NULL && l->type == j_error) { + freetree(comp); + freetree(r); + return l; + } + if (r->type == j_error) { + freetree(l); + freetree(comp); + return r; + } + /* shortcut to optimize non-not constructions */ if (comp == NULL && l == NULL) return r; - /* optimise the case where comp is _NOT, and r is a variable to - * rewrite its comp to _NEQUALS */ - if (comp->nval == _NOT && r->type == j_pred && - r->tval2->nval == _EQUALS) + /* optimise the case where comp is j_not, and r is a variable to + * rewrite its comp to j_nequal */ + if (comp->cval == j_not && r->type == j_pred && + r->tval2->cval == j_equals) { - r->tval2->nval = _NEQUAL; + r->tval2->cval = j_nequal; freetree(l); freetree(comp); return r; } + if (r->type == j_bool && comp->cval != j_nequal && comp->cval != j_equals) + { + freetree(l); + freetree(comp); + freetree(r); + + res = GDKzalloc(sizeof(tree)); + res->type = j_error; + res->sval = GDKstrdup("filter: can only apply equality tests with booleans"); + return res; + } + res = GDKzalloc(sizeof(tree)); res->type = j_pred; res->tval1 = l; @@ -393,7 +433,7 @@ make_pair(char *name, tree *val) if (val->tval1 == NULL) { /* we can't do arithmetic with these */ res->type = j_error; - res->sval = GDKstrdup("a pair needs a name"); + res->sval = GDKstrdup("transform: a pair needs a name"); freetree(val); return res; } @@ -485,7 +525,7 @@ make_operation(tree *var1, tree *op, tre { /* we can't do arithmetic with these */ res->type = j_error; - res->sval = GDKstrdup("cannot perform arithmetic on " + res->sval = GDKstrdup("transform: cannot perform arithmetic on " "string or boolean values"); freetree(var1); freetree(op); diff --git a/monetdb5/extras/jaql/jaqlgencode.c b/monetdb5/extras/jaql/jaqlgencode.c --- a/monetdb5/extras/jaql/jaqlgencode.c +++ b/monetdb5/extras/jaql/jaqlgencode.c @@ -159,15 +159,19 @@ dumprefvar(MalBlkPtr mb, tree *t, int el } /* returns bat with in the head the oids from elems that match the - * predicate */ + * comparison */ static int -dumppred(MalBlkPtr mb, tree *t, int elems, int j1, int j2, int j3, int j4, int j6, int j7) +dumpcomp(MalBlkPtr mb, tree *t, int elems, int j1, int j2, int j3, int j4, int j6, int j7) { InstrPtr q; int a, b, c, d, e, f, g; - assert(t != NULL && t->tval1->type == j_var); + assert(t != NULL); + assert(t->tval1->type == j_var); assert(t->tval2->type == j_comp); + assert(t->tval3->type == j_var + || t->tval3->type == j_num || t->tval3->type == j_dbl + || t->tval3->type == j_str || t->tval3->type == j_bool); a = dumprefvar(mb, t->tval1, elems, j1, j6, j7); if (t->tval3->type != j_var) { @@ -240,12 +244,19 @@ dumppred(MalBlkPtr mb, tree *t, int elem b = getArg(q, 0); pushInstruction(mb, q); q = newInstruction(mb, ASSIGNsymbol); + setModuleId(q, algebraRef); + setFunctionId(q, uselectRef); q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any)); - /* FIXME: this pre-selects equality */ - q = pushChr(mb, q, t->tval3->nval == 0 ? 'f' : 't'); - c = getArg(q, 0); + q = pushArgument(mb, q, b); + /* boolean conditions can only be j_equals or j_nequal */ + if (t->tval2->cval == j_equals) { + q = pushChr(mb, q, t->tval3->nval == 0 ? 'f' : 't'); + } else { + q = pushChr(mb, q, t->tval3->nval != 0 ? 'f' : 't'); + } + b = getArg(q, 0); pushInstruction(mb, q); - break; + return b; _______________________________________________ Checkin-list mailing list [email protected] http://mail.monetdb.org/mailman/listinfo/checkin-list
