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 checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list