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
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list