Changeset: 05426c8cd12b for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=05426c8cd12b
Modified Files:
        monetdb5/extras/jaql/Tests/transform00.stable.out
        monetdb5/extras/jaql/jaql.c
        monetdb5/extras/jaql/jaql.h
        monetdb5/extras/jaql/jaql.mal
        monetdb5/extras/jaql/jaqlfunc.mal
        monetdb5/extras/jaql/jaqlgencode.c
        monetdb5/extras/jaql/jaqltests/Tests/calculations.jaql
        monetdb5/extras/jaql/jaqltests/Tests/calculations.stable.out
        monetdb5/mal/mal_instruction.c
Branch: default
Log Message:

Merge with Oct2012 branch.


diffs (truncated from 541 to 300 lines):

diff --git a/monetdb5/extras/jaql/Tests/transform00.stable.out 
b/monetdb5/extras/jaql/Tests/transform00.stable.out
--- a/monetdb5/extras/jaql/Tests/transform00.stable.out
+++ b/monetdb5/extras/jaql/Tests/transform00.stable.out
@@ -15,7 +15,6 @@ stdout of test 'transform00` in director
 # 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;");
     jaql.x("[1,2,3] -> transform {\"value\":2 + 2};");
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
@@ -1162,8 +1162,9 @@ make_op(enum comptype t)
 
 /* create an operation over two vars/literals, apply some simple rules
  * to reduce work lateron (e.g. static calculations)
- * return is either a j_num, j_dbl or j_operation with tval1 being j_val
- * or j_operation and tval2 being j_num, j_dbl, j_val or j_operation */
+ * return is either a j_num, j_dbl, j_str or j_operation with tval1
+ * being j_val or j_operation and tval2 being j_num, j_dbl, j_val or
+ * j_operation */
 tree *
 make_operation(tree *var1, tree *op, tree *var2)
 {
@@ -1173,13 +1174,13 @@ make_operation(tree *var1, tree *op, tre
        assert(op != NULL && op->type == j_op);
        assert(var2 != NULL);
 
-       if (var1->type == j_bool || var1->type == j_str ||
-                       var2->type == j_bool || var2->type == j_str)
+       if (var1->type == j_bool || var1->type == j_null ||
+                       var2->type == j_bool || var2->type == j_null)
        {
                /* we can't do arithmetic with these */
                res->type = j_error;
                res->sval = GDKstrdup("transform: cannot perform arithmetic on "
-                               "string or boolean values");
+                               "null or boolean values");
                freetree(var1);
                freetree(op);
                freetree(var2);
@@ -1197,7 +1198,32 @@ make_operation(tree *var1, tree *op, tre
                        var2->dval = (double)var2->nval;
                switch (op->cval) {
                        case j_plus:
-                               if (var1->type == j_dbl || var2->type == j_dbl) 
{
+                               if (var1->type == j_str || var2->type == j_str) 
{
+                                       size_t tsize;
+
+                                       if (var1->type != var2->type) {
+                                               res->type = j_error;
+                                               res->sval = 
GDKstrdup("transform: can only concatenate "
+                                                               "two strings");
+                                               freetree(var1);
+                                               freetree(op);
+                                               freetree(var2);
+                                               return res;
+                                       }
+
+                                       tsize = strlen(var1->sval) + 
strlen(var2->sval) + 1;
+                                       res->type = j_str;
+                                       if ((res->sval = GDKmalloc(tsize)) == 
NULL) {
+                                               res->type = j_error;
+                                               res->sval = 
GDKstrdup("transform: str concat: "
+                                                               "out of 
memory");
+                                               freetree(var1);
+                                               freetree(op);
+                                               freetree(var2);
+                                               return res;
+                                       }
+                                       snprintf(res->sval, tsize, "%s%s", 
var1->sval, var2->sval);
+                               } else if (var1->type == j_dbl || var2->type == 
j_dbl) {
                                        res->type = j_dbl;
                                        res->dval = var1->dval + var2->dval;
                                } else {
@@ -1206,7 +1232,15 @@ make_operation(tree *var1, tree *op, tre
                                }
                                break;
                        case j_min:
-                               if (var1->type == j_dbl || var2->type == j_dbl) 
{
+                               if (var1->type == j_str || var2->type == j_str) 
{
+                                       res->type = j_error;
+                                       res->sval = GDKstrdup("transform: 
cannot perform "
+                                                       "minus on strings");
+                                       freetree(var1);
+                                       freetree(op);
+                                       freetree(var2);
+                                       return res;
+                               } else if (var1->type == j_dbl || var2->type == 
j_dbl) {
                                        res->type = j_dbl;
                                        res->dval = var1->dval - var2->dval;
                                } else {
@@ -1215,7 +1249,15 @@ make_operation(tree *var1, tree *op, tre
                                }
                                break;
                        case j_multiply:
-                               if (var1->type == j_dbl || var2->type == j_dbl) 
{
+                               if (var1->type == j_str || var2->type == j_str) 
{
+                                       res->type = j_error;
+                                       res->sval = GDKstrdup("transform: 
cannot perform "
+                                                       "multiplication on 
strings");
+                                       freetree(var1);
+                                       freetree(op);
+                                       freetree(var2);
+                                       return res;
+                               } else if (var1->type == j_dbl || var2->type == 
j_dbl) {
                                        res->type = j_dbl;
                                        res->dval = var1->dval * var2->dval;
                                } else {
@@ -1224,7 +1266,15 @@ make_operation(tree *var1, tree *op, tre
                                }
                                break;
                        case j_divide:
-                               if (var1->type == j_dbl || var2->type == j_dbl) 
{
+                               if (var1->type == j_str || var2->type == j_str) 
{
+                                       res->type = j_error;
+                                       res->sval = GDKstrdup("transform: 
cannot perform "
+                                                       "division on strings");
+                                       freetree(var1);
+                                       freetree(op);
+                                       freetree(var2);
+                                       return res;
+                               } else if (var1->type == j_dbl || var2->type == 
j_dbl) {
                                        res->type = j_dbl;
                                        res->dval = var1->dval / var2->dval;
                                } else {
@@ -2092,3 +2142,69 @@ JAQLcast(Client cntxt, MalBlkPtr mb, Mal
        *ret = *b;
        return MAL_SUCCEED;
 }
+
+/* BAT-wise string concat, currently missing in-core */
+str
+JAQLbatconcat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+       int *ret = (int *)getArgReference(stk, pci, 0);
+       int *l = (int *)getArgReference(stk, pci, 1);
+       int *r = (int *)getArgReference(stk, pci, 2);
+       BAT *left, *right, *b;
+       BATiter bil, bir;
+       BUN pl, ql, pr;
+       char *vall, *valr, *valc;
+       size_t valsize, valcsize = 1024;
+
+       (void)mb;
+       (void)cntxt;
+
+       left = BATdescriptor(ABS(*l));
+       if (*l < 0)
+               left = BATmirror(left);
+       right = BATdescriptor(ABS(*r));
+       if (*r < 0)
+               right = BATmirror(right);
+
+       bil = bat_iterator(left);
+       bir = bat_iterator(right);
+
+       if (BATcount(left) != BATcount(right))
+               throw(MAL, "jaql.batconcat", "both input BATs must have same 
count");
+
+       if (left->ttype != TYPE_str || right->ttype != TYPE_str)
+               throw(MAL, "jaql.batconcat", "BAT tail types must be str");
+
+       b = BATnew(TYPE_oid, TYPE_str, BATcount(left));
+       if (b == NULL)
+               throw(MAL, "jaql.batconcat", "failed to create return BAT");
+
+       valc = GDKmalloc(valcsize);
+       if (valc == NULL)
+               throw(MAL, "jaql.batconcat", "failed to allocate memory "
+                               "for result string");
+
+       for (ql = BUNlast(left), pl = BUNfirst(left), pr = BUNfirst(right); pl 
< ql; pl++, pr++) {
+               vall = (char *)BUNtail(bil, pl);
+               valr = (char *)BUNtail(bir, pr);
+               valsize = strlen(vall) + strlen(valr);
+
+               if (valsize >= valcsize) {
+                       GDKfree(valc);
+                       valcsize = valsize + 24;  /* allocate some extra for 
the future */
+                       valc = GDKmalloc(valcsize);
+                       if (valc == NULL) {
+                               BBPunfix(b->batCacheid);
+                               throw(MAL, "jaql.batconcat", "failed to 
allocate memory "
+                                               "for result string");
+                       }
+               }
+               snprintf(valc, valcsize, "%s%s", vall, valr);
+               BUNins(b, BUNhead(bil, pl), valc, FALSE);
+       }
+       GDKfree(valc);
+
+       BBPkeepref(b->batCacheid);
+       *ret = b->batCacheid;
+       return MAL_SUCCEED;
+}
diff --git a/monetdb5/extras/jaql/jaql.h b/monetdb5/extras/jaql/jaql.h
--- a/monetdb5/extras/jaql/jaql.h
+++ b/monetdb5/extras/jaql/jaql.h
@@ -42,6 +42,7 @@ jaql_export str JAQLexecute(Client cntxt
 jaql_export str JAQLgetVar(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
 jaql_export str JAQLsetVar(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
 jaql_export str JAQLcast(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
+jaql_export str JAQLbatconcat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 
 #endif
 
diff --git a/monetdb5/extras/jaql/jaql.mal b/monetdb5/extras/jaql/jaql.mal
--- a/monetdb5/extras/jaql/jaql.mal
+++ b/monetdb5/extras/jaql/jaql.mal
@@ -37,6 +37,10 @@ pattern cast(b:bat[:oid,:any], t:any_1):
 address JAQLcast
 comment "Return BAT b as BAT with tail type of t, if the BAT tail in reality 
is of that type";
 
+pattern batconcat(l:bat[:oid,:str], r:bat[:oid,:str]):bat[:oid,:str]
+address JAQLbatconcat
+comment "Return the string concatenation of the tails of both input BATs";
+
 # scenario functions and init call
 command prelude()
 address JAQLprelude;
diff --git a/monetdb5/extras/jaql/jaqlfunc.mal 
b/monetdb5/extras/jaql/jaqlfunc.mal
--- a/monetdb5/extras/jaql/jaqlfunc.mal
+++ b/monetdb5/extras/jaql/jaqlfunc.mal
@@ -305,6 +305,8 @@ function count(v:bat[:oid,:any]):bat[:oi
        return r;
 end count;
 
+# generates a continuous array of numbers
+# http://code.google.com/p/jaql/wiki/Builtin_functions#range()
 function range(start:bat[:oid,:lng], vend:bat[:oid,:lng], 
skip:bat[:oid,:lng]):bat[:oid,:lng];
        ret := bat.new(:oid,:lng);
        barrier (h,t) := iterator.new(start);
@@ -321,13 +323,11 @@ function range(start:bat[:oid,:lng], ven
        exit (h,t);
        return ret;
 end range;
-
 function range(start:bat[:oid,:lng], vend:bat[:oid,:lng]):bat[:oid,:lng];
        step := algebra.project(start, 1:lng);
        ret := jaqlfunc.range(start, vend, step);
        return ret;
 end range;
-
 function range(size:bat[:oid,:lng]):bat[:oid,:lng];
        start := algebra.project(size, 0:lng);
        vend := batcalc.-(size,1);
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
@@ -2877,7 +2877,7 @@ dumpvariabletransformation(jc *j, Client
                case j_operation: {
                        int r, s;
                        int u = -1, v;
-                       int h, i, k = -1, l = -1, m;
+                       int h, i, k = -1, l = -1, m, n = -1;
                        InstrPtr p;
                        b = c = -1;
                        switch (t->tval1->type) {
@@ -2885,6 +2885,7 @@ dumpvariabletransformation(jc *j, Client
                                case j_operation:
                                case j_num:
                                case j_dbl:
+                               case j_str:
                                        b = dumpvariabletransformation(j, 
cntxt, mb, t->tval1, elems);
 
                                        q = newInstruction(mb, ASSIGNsymbol);
@@ -2912,6 +2913,7 @@ dumpvariabletransformation(jc *j, Client
                        switch (t->tval3->type) {
                                case j_var:
                                case j_operation:
+                               case j_str:
                                        c = dumpvariabletransformation(j, 
cntxt, mb, t->tval3, elems);
 
                                        q = newInstruction(mb, ASSIGNsymbol);
@@ -3055,6 +3057,131 @@ dumpvariabletransformation(jc *j, Client
                                v = f;
                        }
 
+                       if (t->tval2->cval == j_plus && c != -1) {
+                               int s1, s2, s3, s4, s5;
+                               /* special case for string concatenations, jaql 
performs
+                                * implicit concat on str/str additions only */
+                               q = newInstruction(mb, ASSIGNsymbol);
+                               setModuleId(q, algebraRef);
+                               setFunctionId(q, semijoinRef);
+                               q = pushReturn(mb, q, newTmpVariable(mb, 
TYPE_any));
+                               q = pushArgument(mb, q, j->j2);
+                               q = pushArgument(mb, q, b);
+                               s1 = getArg(q, 0);
+                               pushInstruction(mb, q);
+                               q = newInstruction(mb, ASSIGNsymbol);
+                               setModuleId(q, algebraRef);
+                               setFunctionId(q, semijoinRef);
+                               q = pushReturn(mb, q, newTmpVariable(mb, 
TYPE_any));
+                               q = pushArgument(mb, q, j->j2);
+                               q = pushArgument(mb, q, c);
+                               s2 = getArg(q, 0);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to