Changeset: 6e47fe588566 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6e47fe588566
Modified Files:
monetdb5/extras/jaql/Tests/All
monetdb5/extras/jaql/Tests/plan00.mal
monetdb5/extras/jaql/Tests/plan00.stable.out
monetdb5/extras/jaql/Tests/transform00.mal
monetdb5/extras/jaql/Tests/transform00.stable.err
monetdb5/extras/jaql/Tests/transform00.stable.out
monetdb5/extras/jaql/jaql.c
monetdb5/extras/jaql/jaql.h
monetdb5/extras/jaql/jaqlgencode.c
monetdb5/extras/jaql/parser/jaql.l
monetdb5/extras/jaql/parser/jaql.y
Branch: jacqueline
Log Message:
jaql: implemented first step towards transform
added parser support for arithmetic
added parser support for construction of JSON objects/arrays
dropped old manual parsing method of transform args
implemented printtree of j_transform nodes
implemented simple case of static value as transform expression in gencode
added test
diffs (truncated from 924 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
@@ -1,5 +1,6 @@
expand00
filter00
+transform00
sort00
top00
variable00
diff --git a/monetdb5/extras/jaql/Tests/plan00.mal
b/monetdb5/extras/jaql/Tests/plan00.mal
--- a/monetdb5/extras/jaql/Tests/plan00.mal
+++ b/monetdb5/extras/jaql/Tests/plan00.mal
@@ -4,9 +4,16 @@ jaql.x("plan test -> filter each emp emp
jaql.x("plan e -> filter $.mgr or $.income > 30000;");
jaql.x("plan emps = [ {id:1, dept:1, income:12000},{id:2, dept:1,
income:13000} ];");
jaql.x("plan [ {id:1, dept:1, income:12000},{id:2, dept:1, income:13000} ] ->
filter $.dept == 1;");
-#jaql.x("plan [ 1, 2, 3 ] -> transform {\"value\":$};");
+
jaql.x("plan [ [3,65,8,72], [5,98,2,65] ] -> expand each arr;");
jaql.x("plan [ {\"name\":\"Jon Doe\", \"movie_ids\":[3,65,8,72]},
{\"name\":\"Jane Dean\",\"movie_ids\":[5,98,2]} ] -> expand $.movie_ids;");
-#jaql.x("plan A -> expand -> transform $ * 2;");
+jaql.x("plan A -> expand -> transform $ * 2;");
jaql.x("plan A -> expand $.ids;");
+jaql.x("plan [1,2,3] -> transform {\"value\":$};");
+jaql.x("plan [1,2,3] -> transform $ * 2;");
+jaql.x("plan [1,2,3] -> transform 2 * $;");
+jaql.x("plan [1,2,3] -> transform 2 * 2;");
+jaql.x("plan [1,2,3] -> transform 2 * ($ * 2);");
+jaql.x("plan [1,2,3] -> transform 2 * 2.0 * $;");
+jaql.x("plan [1,2,3] -> transform ($ * 2.0) / 4;");
diff --git a/monetdb5/extras/jaql/Tests/plan00.stable.out
b/monetdb5/extras/jaql/Tests/plan00.stable.out
--- a/monetdb5/extras/jaql/Tests/plan00.stable.out
+++ b/monetdb5/extras/jaql/Tests/plan00.stable.out
@@ -23,11 +23,17 @@ function user.main():void;
jaql.x("plan e -> filter $.mgr or $.income > 30000;");
jaql.x("plan emps = [ {id:1, dept:1, income:12000},{id:2, dept:1,
income:13000} ];");
jaql.x("plan [ {id:1, dept:1, income:12000},{id:2, dept:1, income:13000} ]
-> filter $.dept == 1;");
-#jaql.x("plan [ 1, 2, 3 ] -> transform {\"value\":$};");
jaql.x("plan [ [3,65,8,72], [5,98,2,65] ] -> expand each arr;");
jaql.x("plan [ {\"name\":\"Jon Doe\", \"movie_ids\":[3,65,8,72]},
{\"name\":\"Jane Dean\",\"movie_ids\":[5,98,2]} ] -> expand $.movie_ids;");
-#jaql.x("plan A -> expand -> transform $ * 2;");
+ jaql.x("plan A -> expand -> transform $ * 2;");
jaql.x("plan A -> expand $.ids;");
+ jaql.x("plan [1,2,3] -> transform {\"value\":$};");
+ jaql.x("plan [1,2,3] -> transform $ * 2;");
+ jaql.x("plan [1,2,3] -> transform 2 * $;");
+ jaql.x("plan [1,2,3] -> transform 2 * 2;");
+ jaql.x("plan [1,2,3] -> transform 2 * ($ * 2);");
+ jaql.x("plan [1,2,3] -> transform 2 * 2.0 * $;");
+ jaql.x("plan [1,2,3] -> transform ($ * 2.0) / 4;");
end main;
B => A
test as $ -> filter: $.mgr == true => <result>
@@ -37,7 +43,15 @@ e as $ -> filter: ( $.mgr == true || $.i
[ {id:1, dept:1, income:12000},{id:2, dept:1, income:13000} ] as $ -> filter:
$.dept == 1 => <result>
[ [3,65,8,72], [5,98,2,65] ] as arr -> expand: arr => <result>
[ {"name":"Jon Doe", "movie_ids":[3,65,8,72]}, {"name":"Jane
Dean","movie_ids":[5,98,2]} ] as $ -> expand: $.movie_ids => <result>
+A as $ -> expand: $ as $ -> transform: ( $ * 2 )
A as $ -> expand: $.ids => <result>
+[1,2,3] as $ -> transform: { "value": $ }
+[1,2,3] as $ -> transform: ( $ * 2 )
+[1,2,3] as $ -> transform: ( $ * 2 )
+[1,2,3] as $ -> transform: 4
+[1,2,3] as $ -> transform: ( ( $ * 2 ) * 2 )
+[1,2,3] as $ -> transform: ( ( $ * 2.000000 ) * 2 )
+[1,2,3] as $ -> transform: ( ( $ * 2.000000 ) / 4 )
# 21:19:49 >
# 21:19:49 > "Done."
diff --git a/monetdb5/extras/jaql/Tests/transform00.mal
b/monetdb5/extras/jaql/Tests/transform00.mal
new file mode 100644
--- /dev/null
+++ b/monetdb5/extras/jaql/Tests/transform00.mal
@@ -0,0 +1,1 @@
+jaql.x("[1,2,3] -> transform 2 * 2;");
diff --git a/monetdb5/extras/jaql/Tests/transform00.stable.err
b/monetdb5/extras/jaql/Tests/transform00.stable.err
new file mode 100644
--- /dev/null
+++ b/monetdb5/extras/jaql/Tests/transform00.stable.err
@@ -0,0 +1,31 @@
+stderr of test 'transform00` in directory 'extras/jaql` itself:
+
+
+# 21:27:12 >
+# 21:27:12 > "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=35341" "--set" "monet_prompt="
"--trace" "--forcemito" "--set" "mal_listing=2" "--dbname=mTests_extras_jaql"
"transform00.mal"
+# 21:27:12 >
+
+# 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 = 35341
+# cmdline opt monet_prompt =
+# cmdline opt mal_listing = 2
+# cmdline opt gdk_dbname = mTests_extras_jaql
+
+# 21:27:13 >
+# 21:27:13 > "Done."
+# 21:27:13 >
+
diff --git a/monetdb5/extras/jaql/Tests/transform00.stable.out
b/monetdb5/extras/jaql/Tests/transform00.stable.out
new file mode 100644
--- /dev/null
+++ b/monetdb5/extras/jaql/Tests/transform00.stable.out
@@ -0,0 +1,27 @@
+stdout of test 'transform00` in directory 'extras/jaql` itself:
+
+
+# 21:27:12 >
+# 21:27:12 > "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=35341" "--set" "monet_prompt="
"--trace" "--forcemito" "--set" "mal_listing=2" "--dbname=mTests_extras_jaql"
"transform00.mal"
+# 21:27:12 >
+
+# MonetDB 5 server v11.8.0 "jacqueline-4b6d0a64f745+"
+# 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:35341/
+# MonetDB/GIS module loaded
+# MonetDB/SQL module loaded
+# MonetDB/DataCell module not loaded: MALException:jaql.context:JAQL
environment not found
+function user.main():void;
+ jaql.x("[1,2,3] -> transform 2 * 2;");
+end main;
+[ 4, 4, 4 ]
+
+# 21:27:13 >
+# 21:27:13 > "Done."
+# 21:27:13 >
+
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
@@ -66,6 +66,30 @@ make_json(char *s)
return res;
}
+tree *
+make_json_object(tree *obj)
+{
+ tree *res = GDKzalloc(sizeof(tree));
+
+ assert(obj != NULL && obj->type == j_pair);
+ res->type = j_json_obj;
+ res->tval1 = obj;
+
+ return res;
+}
+
+tree *
+make_json_array(tree *arr)
+{
+ tree *res = GDKzalloc(sizeof(tree));
+
+ assert(arr != NULL); /* arr can be about everything */
+ res->type = j_json_arr;
+ res->tval1 = arr;
+
+ return res;
+}
+
/* append naction as next pipe after oaction */
tree *
append_jaql_pipe(tree *oaction, tree *naction)
@@ -102,6 +126,38 @@ make_jaql_filter(tree *var, tree *pred)
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)
+{
+ tree *res = NULL;
+
+ if (t == NULL)
+ return res;
+
+ if (t->type == j_var) {
+ if (strcmp(var, t->sval) != 0) {
+ char buf[128];
+ res = GDKzalloc(sizeof(tree));
+ snprintf(buf, sizeof(buf), "transform: unknown
variable: %s",
+ t->sval);
+ res->type = j_error;
+ res->sval = GDKstrdup(buf);
+ }
+ return res;
+ }
+
+ if ((res = _check_exp_var(var, t->tval1)) != NULL)
+ return res;
+ if ((res = _check_exp_var(var, t->tval2)) != NULL)
+ return res;
+ if ((res = _check_exp_var(var, t->tval3)) != NULL)
+ return res;
return res;
}
@@ -111,55 +167,20 @@ make_jaql_filter(tree *var, tree *pred)
tree *
make_jaql_transform(tree *var, tree *tmpl)
{
- tree *res = GDKzalloc(sizeof(tree));
- char buf[8096];
- char *p, *q, *r;
- size_t l;
- tree *t;
+ tree *res;
- /* process tmpl, to turn into a C-like printf string and extract
- * variable references */
- for (p = tmpl->sval, q = buf; *p != '\0' && q - buf < 8096; p++, q++)
- {
- l = strlen(var->sval);
- if (*p == *var->sval && strncmp(p, var->sval, l) == 0 &&
- !(p[l] >= 'A' && p[l] <= 'Z') &&
- !(p[l] >= 'a' && p[l] <= 'z') &&
- !(p[l] >= '0' && p[l] <= '9') && p[l] != '_')
- {
- p += l;
- if (res->tval3 == NULL) {
- t = res->tval3 = make_varname(var->sval);
- } else {
- t = t->next = make_varname(var->sval);
- }
- *q++ = '%';
- *q++ = 's';
+ assert(var != NULL && var->type == j_var);
+ assert(tmpl != NULL);
- while (*p == '.') {
- r = p;
- for (; *p != '\0'; p++) {
- if (*p != '_' &&
- !(p[l] >= 'A' && p[l]
<= 'Z') &&
- !(p[l] >= 'a' && p[l]
<= 'z') &&
- !(p[l] >= '0' && p[l]
<= '9'))
- {
- *q = *p;
- *p = '\0';
- append_varname(t, r);
- *p = *q;
- }
- }
- }
- /* we don't support x[n] yet */
- }
- *q = *p;
+ /* traverse down tmpl, searching for all variable references to
+ * check if they refer to var */
+ if ((res = _check_exp_var(var->sval, tmpl)) != NULL) {
+ freetree(var);
+ freetree(tmpl);
+ return(res);
}
- *q = '\0';
- GDKfree(tmpl->sval);
- tmpl->sval = GDKstrdup(buf);
-
+ res = GDKzalloc(sizeof(tree));
res->type = j_transform;
res->tval1 = var;
res->tval2 = tmpl;
@@ -351,6 +372,67 @@ append_varname(tree *var, char *ident)
return var;
}
+/* constructs a JSON pair '"name": val' where val can be an expression
+ * or a literal value
+ * if name is NULL, val must be a variable, and the pair constructed
+ * will be named after the (last part of the) variable */
+tree *
+make_pair(char *name, tree *val)
+{
+ tree *res = GDKzalloc(sizeof(tree));
+
+ assert(val != NULL);
+ assert(name != NULL || val->type == j_var);
+
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list