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

Reply via email to