Changeset: f501170bee19 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=f501170bee19
Modified Files:
ctest/tools/monetdbe/example_proxy.c
design.txt
monetdb5/modules/mal/remote.c
monetdb5/optimizer/opt_prelude.c
monetdb5/optimizer/opt_prelude.h
sql/backends/monet5/sql_execute.c
tools/monetdbe/monetdbe.c
Branch: monetdbe-proxy
Log Message:
Basic functionality monetdbe/remote proxy is working.
diffs (truncated from 574 to 300 lines):
diff --git a/ctest/tools/monetdbe/example_proxy.c
b/ctest/tools/monetdbe/example_proxy.c
--- a/ctest/tools/monetdbe/example_proxy.c
+++ b/ctest/tools/monetdbe/example_proxy.c
@@ -33,12 +33,76 @@ main(void)
if (monetdbe_open(&mdbe,
"mapi:monetdb://127.0.0.1:50000?database=devdb", &opt))
error("Failed to open database")
+ if ((err = monetdbe_query(mdbe, "SELECT x, y, 1 AS some_int FROM test;
", &result, NULL)) != NULL)
+ error(err)
+
+ fprintf(stdout, "Query result with %zu cols and %"PRId64" rows\n",
result->ncols, result->nrows);
+ for (int64_t r = 0; r < result->nrows; r++) {
+ for (size_t c = 0; c < result->ncols; c++) {
+ monetdbe_column* rcol;
+ if ((err = monetdbe_result_fetch(result, &rcol, c)) !=
NULL)
+ error(err)
+ switch (rcol->type) {
+ case monetdbe_int8_t: {
+ monetdbe_column_int8_t * col =
(monetdbe_column_int8_t *) rcol;
+ if (col->data[r] == col->null_value) {
+ printf("NULL");
+ } else {
+ printf("%d", col->data[r]);
+ }
+ break;
+ }
+ case monetdbe_int16_t: {
+ monetdbe_column_int16_t * col =
(monetdbe_column_int16_t *) rcol;
+ if (col->data[r] == col->null_value) {
+ printf("NULL");
+ } else {
+ printf("%d", col->data[r]);
+ }
+ break;
+ }
+ case monetdbe_int32_t: {
+ monetdbe_column_int32_t * col =
(monetdbe_column_int32_t *) rcol;
+ if (col->data[r] == col->null_value) {
+ printf("NULL");
+ } else {
+ printf("%d", col->data[r]);
+ }
+ break;
+ }
+ case monetdbe_str: {
+ monetdbe_column_str * col =
(monetdbe_column_str *) rcol;
+ if (col->is_null(col->data[r])) {
+ printf("NULL");
+ } else {
+ printf("%s", (char*)
col->data[r]);
+ }
+ break;
+ }
+ default: {
+ printf("UNKNOWN");
+ }
+ }
+
+ if (c + 1 < result->ncols) {
+ printf(", ");
+ }
+ }
+ printf("\n");
+ }
+
+ if ((err = monetdbe_cleanup_result(mdbe, result)) != NULL)
+ error(err)
+
+ if ((err = monetdbe_query(mdbe, "INSERT INTO test VALUES (100,
'temp');", NULL, NULL)) != NULL)
+ error(err)
+
// Assumes the existance of a table test (x INT, y STRING) on the
remote.
monetdbe_statement *stmt = NULL;
- if ((err = monetdbe_prepare(mdbe, "SELECT y, 1 FROM test WHERE x = ?",
&stmt)) != NULL)
+ if ((err = monetdbe_prepare(mdbe, "SELECT y, x, 1 AS some_fixed_int
FROM test WHERE x = ?", &stmt)) != NULL)
error(err)
- int x = 10;
+ int x = 100;
if ((err = monetdbe_bind(stmt, &x, 0)) != NULL)
error(err)
@@ -104,9 +168,6 @@ main(void)
if ((err = monetdbe_cleanup_result(mdbe, result)) != NULL)
error(err)
- if ((err = monetdbe_query(mdbe, "DELETE FROM test where x = 100;",
NULL, NULL)) != NULL)
- error(err)
-
if ((err = monetdbe_query(mdbe, "SELECT x, y, 1 AS some_int FROM test
WHERE x > 10; ", &result, NULL)) != NULL)
error(err)
@@ -165,6 +226,9 @@ main(void)
printf("\n");
}
+ if ((err = monetdbe_query(mdbe, "DELETE FROM test where x = 100;",
NULL, NULL)) != NULL)
+ error(err)
+
if ((err = monetdbe_cleanup_result(mdbe, result)) != NULL)
error(err)
diff --git a/design.txt b/design.txt
--- a/design.txt
+++ b/design.txt
@@ -98,3 +98,16 @@ Plan
Expand sqlStatementIntern to incorporate prepared statements.
use remote to call sql.prepare on the remote side. Remote should return
similar info as regular mapi.
+
+
+function user.%2():any;
+ X_0:any := remote.put("_monetdb_0":str, true:bit);
+ X_3:any := remote.put("_monetdb_0":str, "SELECT x, y, 1 AS some_int FROM
test WHERE x > 10; ":str);
+ remote.exec("_monetdb_0":str, "sql":str, "eval":str, 0x7fffffffdba0:ptr,
X_3:any, X_0:any);
+ return :void;
+
+function user.%2():any;
+ X_0:str := remote.put("_monetdb_0":str, true:bit);
+ X_3:str := remote.put("_monetdb_0":str, "SELECT x, y, 1 AS some_int FROM
test WHERE x > 10; ":str);
+ remote.exec("_monetdb_0":str, "sql":str, "eval":str, 0x7fffffffdba0:ptr,
X_3:str, X_0:str);
+ return :void;
diff --git a/monetdb5/modules/mal/remote.c b/monetdb5/modules/mal/remote.c
--- a/monetdb5/modules/mal/remote.c
+++ b/monetdb5/modules/mal/remote.c
@@ -1194,11 +1194,19 @@ str RMTexec(Client cntxt, MalBlkPtr mb,
(void)cntxt;
(void)mb;
- for (i = 0; i < pci->retc; i++) {
- tmp = *getArgReference_str(stk, pci, i);
- if (tmp == NULL || strcmp(tmp, (str)str_nil) == 0)
- throw(ILLARG, "remote.exec", ILLEGAL_ARGUMENT
- ": return value %d is NULL or nil", i);
+ columnar_result_callback* rcb = NULL;
+ ValRecord *v = &(stk)->stk[(pci)->argv[4]];
+ if (pci->retc == 1 && (pci->argc >= 4) && (v->vtype == TYPE_ptr) ) {
+ rcb = (columnar_result_callback*) v->val.pval;
+ i = 1; //There is only one (void) return argument.
+ }
+ else {
+ for (i = 0; i < pci->retc; i++) {
+ tmp = *getArgReference_str(stk, pci, i);
+ if (tmp == NULL || strcmp(tmp, (str)str_nil) == 0)
+ throw(ILLARG, "remote.exec", ILLEGAL_ARGUMENT
+ ": return value %d is NULL or
nil", i);
+ }
}
conn = *getArgReference_str(stk, pci, i++);
if (conn == NULL || strcmp(conn, (str)str_nil) == 0)
@@ -1216,11 +1224,6 @@ str RMTexec(Client cntxt, MalBlkPtr mb,
/* this call should be a single transaction over the channel*/
MT_lock_set(&c->lock);
- columnar_result_callback* rcb = NULL;
- ValRecord *v = &(stk)->stk[(pci)->argv[3]];
- if (pci->retc == 0 && (pci->argc >= 4) && (v->vtype == TYPE_ptr) ) {
- rcb = (columnar_result_callback*) v->val.pval;
- }
if(!rcb && pci->argc - pci->retc < 3) /* conn, mod, func, ... */
throw(MAL, "remote.exec", ILLEGAL_ARGUMENT " MAL instruction
misses arguments");
@@ -1228,14 +1231,14 @@ str RMTexec(Client cntxt, MalBlkPtr mb,
len = 0;
/* count how big a buffer we need */
len += 2 * (pci->retc > 1);
- for (i = 0; i < pci->retc; i++) {
- len += 2 * (i > 0);
- len += strlen(*getArgReference_str(stk, pci, i));
- }
+ if (!rcb)
+ for (i = 0; i < pci->retc; i++) {
+ len += 2 * (i > 0);
+ len += strlen(*getArgReference_str(stk, pci, i));
+ }
const int arg_index = rcb?4:3;
-
len += strlen(mod) + strlen(func) + 6;
for (i = arg_index; i < pci->argc - pci->retc; i++) {
len += 2 * (i > arg_index);
@@ -1250,16 +1253,17 @@ str RMTexec(Client cntxt, MalBlkPtr mb,
if (pci->retc > 1)
qbuf[len++] = '(';
- for (i = 0; i < pci->retc; i++)
- len += snprintf(&qbuf[len], buflen - len, "%s%s",
- (i > 0 ? ", " : ""), *getArgReference_str(stk,
pci, i));
+ if (!rcb)
+ for (i = 0; i < pci->retc; i++)
+ len += snprintf(&qbuf[len], buflen - len, "%s%s",
+ (i > 0 ? ", " : ""),
*getArgReference_str(stk, pci, i));
if (pci->retc > 1)
qbuf[len++] = ')';
/* build the function invocation string in qbuf */
- if (pci->retc > 0) {
+ if (!rcb && pci->retc > 0) {
len += snprintf(&qbuf[len], buflen - len, " := %s.%s(", mod,
func);
}
else {
@@ -1288,14 +1292,7 @@ str RMTexec(Client cntxt, MalBlkPtr mb,
int fields = mapi_get_field_count(mhdl);
- columnar_result* results = GDKzalloc(sizeof(columnar_result) *
fields);
-
- for (int i = 0; i < fields; i++) {
- char* s = mapi_get_name(mhdl, i);
- if (s == NULL)
- s = "";
- printf("%s%s\n", " ", s);
- }
+ columnar_result* results = GDKzalloc(sizeof(columnar_result) *
fields);
char buf[256] = {0};
@@ -1330,6 +1327,7 @@ str RMTexec(Client cntxt, MalBlkPtr mb,
}
else {
tmp = rcb->call(rcb->context, tblname, results, fields);
+ GDKfree(rcb);
}
GDKfree(results);
}
@@ -1585,7 +1583,8 @@ mel_func remote_init_funcs[] = {
pattern("remote", "exec", RMTexec, false, "remotely executes <mod>.<func> and
returns the handle to its result", args(1,4,
vararg("",str),arg("conn",str),arg("mod",str),arg("func",str))),
pattern("remote", "exec", RMTexec, false, "remotely executes <mod>.<func>
using the argument list of remote objects and returns the handle to its
result", args(1,5,
arg("",str),arg("conn",str),arg("mod",str),arg("func",str),vararg("",str))),
pattern("remote", "exec", RMTexec, false, "remotely executes <mod>.<func>
using the argument list of remote objects and returns the handle to its
result", args(1,5,
vararg("",str),arg("conn",str),arg("mod",str),arg("func",str),vararg("",str))),
- pattern("remote", "exec", RMTexec, false, "remotely executes <mod>.<func>
using the argument list of remote objects using and applying function pointer
rcb as result handling callback.", args(1,5,
vararg("",str),arg("conn",str),arg("mod",str),arg("func",str),arg("rcb",ptr))),
+ pattern("remote", "exec", RMTexec, false, "remotely executes <mod>.<func>
using the argument list of remote objects using and applying function pointer
rcb as result handling callback.", args(1,6,
vararg("",str),arg("conn",str),arg("mod",str),arg("func",str),arg("rcb",ptr),
vararg("",str))),
+ pattern("remote", "exec2", RMTexec, false, "remotely executes <mod>.<func>
using the argument list of remote objects using and applying function pointer
rcb as result handling callback.", args(0,5,
arg("conn",str),arg("mod",str),arg("func",str),arg("rcb",ptr), vararg("",str))),
command("remote", "isalive", RMTisalive, false, "check if conn is still valid
and connected", args(1,2, arg("",int),arg("conn",str))),
pattern("remote", "batload", RMTbatload, false, "create a BAT of the given
type and size, and load values from the input stream", args(1,3,
batargany("",1),argany("tt",1),arg("size",int))),
pattern("remote", "batbincopy", RMTbincopyto, false, "dump BAT b in binary
form to the stream", args(1,2, arg("",void),batargany("b",0))),
diff --git a/monetdb5/optimizer/opt_prelude.c b/monetdb5/optimizer/opt_prelude.c
--- a/monetdb5/optimizer/opt_prelude.c
+++ b/monetdb5/optimizer/opt_prelude.c
@@ -125,6 +125,7 @@ str emptybindRef;
str eqRef;
str evalRef;
str execRef;
+str exec2Ref;
str expandRef;
str exportOperationRef;
str export_tableRef;
@@ -432,6 +433,7 @@ void optimizerInit(void)
eqRef = putName("==");
evalRef = putName("eval");
execRef = putName("exec");
+ exec2Ref = putName("exec2");
expandRef = putName("expand");
exportOperationRef = putName("exportOperation");
export_tableRef = putName("export_table");
diff --git a/monetdb5/optimizer/opt_prelude.h b/monetdb5/optimizer/opt_prelude.h
--- a/monetdb5/optimizer/opt_prelude.h
+++ b/monetdb5/optimizer/opt_prelude.h
@@ -122,6 +122,7 @@ mal_export str emptybindRef;
mal_export str eqRef;
mal_export str evalRef;
mal_export str execRef;
+mal_export str exec2Ref;
mal_export str expandRef;
mal_export str exportOperationRef;
mal_export str export_tableRef;
diff --git a/sql/backends/monet5/sql_execute.c
b/sql/backends/monet5/sql_execute.c
--- a/sql/backends/monet5/sql_execute.c
+++ b/sql/backends/monet5/sql_execute.c
@@ -324,6 +324,7 @@ SQLstatementIntern(Client c, str *expr,
stream *buf = NULL;
str msg = MAL_SUCCEED;
backend *be = NULL, *sql = (backend *) c->sqlcontext;
+ Symbol backup = NULL;
size_t len = strlen(*expr);
#ifdef _SQL_COMPILE
@@ -424,6 +425,11 @@ SQLstatementIntern(Client c, str *expr,
* Scan the complete string for SQL statements, stop at the first error.
*/
c->sqlcontext = sql;
+ if (c->curprg) {
+ backup = c->curprg;
+ c->curprg = NULL;
+ }
+
while (msg == MAL_SUCCEED && m->scanner.rs->pos < m->scanner.rs->len) {
sql_rel *r;
@@ -629,6 +635,9 @@ endofcompile:
if (execute)
MSresetInstructions(c->curprg->def, 1);
+ if (backup)
+ c->curprg = backup;
+
c->sqlcontext = be;
backend_destroy(sql);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list