Changeset: 3890962bb839 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3890962bb839 Branch: default Log Message:
Merge with monetdbe-proxy. diffs (truncated from 1143 to 300 lines): diff --git a/clients/Tests/MAL-signatures.stable.out b/clients/Tests/MAL-signatures.stable.out --- a/clients/Tests/MAL-signatures.stable.out +++ b/clients/Tests/MAL-signatures.stable.out @@ -8771,6 +8771,7 @@ stdout of test 'MAL-signatures` in direc [ "inspect", "getDefinition", "pattern inspect.getDefinition(X_1:str, X_2:str):bat[:str] ", "INSPECTgetDefinition;", "" ] [ "inspect", "getEnvironment", "command inspect.getEnvironment() (X_0:bat[:str], X_1:bat[:str]) ", "INSPECTgetEnvironment;", "" ] [ "inspect", "getEnvironment", "command inspect.getEnvironment(X_1:str):str ", "INSPECTgetEnvironmentKey;", "" ] +[ "inspect", "getExistence", "pattern inspect.getExistence(X_1:str, X_2:str):bit ", "INSPECTgetExistence;", "" ] [ "inspect", "getFunction", "pattern inspect.getFunction():bat[:str] ", "INSPECTgetAllFunctions;", "" ] [ "inspect", "getKind", "pattern inspect.getKind():bat[:str] ", "INSPECTgetkind;", "" ] [ "inspect", "getModule", "pattern inspect.getModule():bat[:str] ", "INSPECTgetAllModules;", "" ] @@ -9244,11 +9245,12 @@ stdout of test 'MAL-signatures` in direc [ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:ptr, X_5:str...):void ", "RMTexec;", "" ] [ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:str...):str ", "RMTexec;", "" ] [ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:str...):str... ", "RMTexec;", "" ] +[ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:str...):void ", "RMTexec;", "" ] [ "remote", "get", "pattern remote.get(X_1:str, X_2:str):any ", "RMTget;", "" ] [ "remote", "isalive", "command remote.isalive(X_1:str):int ", "RMTisalive;", "" ] [ "remote", "prelude", "command remote.prelude():void ", "RMTprelude;", "" ] [ "remote", "put", "pattern remote.put(X_1:str, X_2:any):str ", "RMTput;", "" ] -[ "remote", "register", "pattern remote.register(X_1:str, X_2:str, X_3:str):void ", "RMTregister;", "" ] +[ "remote", "register", "pattern remote.register(X_1:str, X_2:str, X_3:str):str ", "RMTregister;", "" ] [ "remote", "register_supervisor", "command remote.register_supervisor(X_1:str, X_2:str):int ", "RMTregisterSupervisor;", "" ] [ "remote", "resolve", "command remote.resolve(X_1:str):bat[:str] ", "RMTresolve;", "" ] [ "sample", "subuniform", "pattern sample.subuniform(X_1:bat[:any], X_2:dbl):bat[:oid] ", "SAMPLEuniform;", "" ] diff --git a/clients/Tests/MAL-signatures.stable.out.int128 b/clients/Tests/MAL-signatures.stable.out.int128 --- a/clients/Tests/MAL-signatures.stable.out.int128 +++ b/clients/Tests/MAL-signatures.stable.out.int128 @@ -12067,6 +12067,7 @@ stdout of test 'MAL-signatures` in direc [ "inspect", "getDefinition", "pattern inspect.getDefinition(X_1:str, X_2:str):bat[:str] ", "INSPECTgetDefinition;", "" ] [ "inspect", "getEnvironment", "command inspect.getEnvironment() (X_0:bat[:str], X_1:bat[:str]) ", "INSPECTgetEnvironment;", "" ] [ "inspect", "getEnvironment", "command inspect.getEnvironment(X_1:str):str ", "INSPECTgetEnvironmentKey;", "" ] +[ "inspect", "getExistence", "pattern inspect.getExistence(X_1:str, X_2:str):bit ", "INSPECTgetExistence;", "" ] [ "inspect", "getFunction", "pattern inspect.getFunction():bat[:str] ", "INSPECTgetAllFunctions;", "" ] [ "inspect", "getKind", "pattern inspect.getKind():bat[:str] ", "INSPECTgetkind;", "" ] [ "inspect", "getModule", "pattern inspect.getModule():bat[:str] ", "INSPECTgetAllModules;", "" ] @@ -12546,11 +12547,12 @@ stdout of test 'MAL-signatures` in direc [ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:ptr, X_5:str...):void ", "RMTexec;", "" ] [ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:str...):str ", "RMTexec;", "" ] [ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:str...):str... ", "RMTexec;", "" ] +[ "remote", "exec", "pattern remote.exec(X_1:str, X_2:str, X_3:str, X_4:str...):void ", "RMTexec;", "" ] [ "remote", "get", "pattern remote.get(X_1:str, X_2:str):any ", "RMTget;", "" ] [ "remote", "isalive", "command remote.isalive(X_1:str):int ", "RMTisalive;", "" ] [ "remote", "prelude", "command remote.prelude():void ", "RMTprelude;", "" ] [ "remote", "put", "pattern remote.put(X_1:str, X_2:any):str ", "RMTput;", "" ] -[ "remote", "register", "pattern remote.register(X_1:str, X_2:str, X_3:str):void ", "RMTregister;", "" ] +[ "remote", "register", "pattern remote.register(X_1:str, X_2:str, X_3:str):str ", "RMTregister;", "" ] [ "remote", "register_supervisor", "command remote.register_supervisor(X_1:str, X_2:str):int ", "RMTregisterSupervisor;", "" ] [ "remote", "resolve", "command remote.resolve(X_1:str):bat[:str] ", "RMTresolve;", "" ] [ "sample", "subuniform", "pattern sample.subuniform(X_1:bat[:any], X_2:dbl):bat[:oid] ", "SAMPLEuniform;", "" ] 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,7 +33,78 @@ 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) + + if ((err = monetdbe_query(mdbe, "DELETE FROM test WHERE x < 0; ", &result, NULL)) != NULL) + error(err) + + if ((err = monetdbe_query(mdbe, "SELECT * FROM test; ", &result, NULL)) != NULL) + error(err) + + monetdbe_column* appendable_columns[2]; + + 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) + appendable_columns[c] = rcol; + 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_append(mdbe, "sys", "test", appendable_columns, 2)) != NULL) + error(err) + + if ((err = monetdbe_cleanup_result(mdbe, result)) != NULL) + error(err) + + if ((err = monetdbe_query(mdbe, "SELECT * FROM test; ", &result, NULL)) != NULL) error(err) fprintf(stdout, "Query result with %zu cols and %"PRId64" rows\n", result->ncols, result->nrows); @@ -110,6 +181,7 @@ main(void) if ((err = monetdbe_execute(stmt, &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++) { diff --git a/design.txt b/design.txt new file mode 100644 --- /dev/null +++ b/design.txt @@ -0,0 +1,113 @@ +Creating a table returning SQL function + + rel_semantic + | + |-> create_funct + |-> rel_psm + |->rel_ceate_func + |->mvc_create_func (just to have an initialized unregistered sql_func object.) + |->rel_create_function (this function add the necessary flags (ddl_create_function) so that CREATE statement is compiled into a DDL msql program and a pointer to the previous object) + + Engine + |->SQLcreate_function + | + |->create_func + |->mvc_create_func now adding it to the session transaction. + |->calls sql_parse with the m_deps flag on the original SQL CREATE FUNCTION query to find the table/column/argument dependencies and add them to the system catalogue. The query is somehow stored together with the function. + + + + +calling a SQL function (SELECT * from bbp();) + + First the outer statements are transormed into nested relational plans + + the BBP() is recognized as a function cal rel2bin_table; + + the will end up in a call to stmt *stmt_Nop(backend *be, stmt *ops, sql_subfunc *f) + which will end up in backend_create_subfunc => backend_create_func => backend_create_sql_func finally ending up in rel_parse with the m_instantiate flag + + We end up with relational subplan which is equivalent to a call to the table returning function + + So backend_create_sql_func will not only parse and optimize the query and its outcoming relational plan, but it will also compile it into a MAL program/function through backend_dumpstmt. + + + So the outer query is compiled into a MAL program that looks like this + + | function user.main():void; | + | X_1:void := querylog.define("explain select * from bbp();":str, "default_pi | + : pe":str, 10:int); : + | barrier X_69:bit := language.dataflow(); | + | X_8:bat[:str] := bat.pack(".%1":str, ".%1":str); | + | X_9:bat[:str] := bat.pack("id":str, "name":str); | + | X_10:bat[:str] := bat.pack("int":str, "clob":str); | + | X_11:bat[:int] := bat.pack(32:int, 0:int); | + | X_12:bat[:int] := bat.pack(0:int, 0:int); | + | (X_5:bat[:int], X_6:bat[:str]) := user.bbp(); | + | exit X_69:bit; | + | sql.resultSet(X_8:bat[:str], X_9:bat[:str], X_10:bat[:str], X_11:bat[:int], | + : X_12:bat[:int], X_5:bat[:int], X_6:bat[:str]); : + | end user.main; + + + Downside is that the user.bbp() function is compiled and optimized separately from the rest of the query + +monetdbe_append(foo, EB1, ..., EBN) + +do sql_table* t = create_sql_table(..., .., tt_table, 0, SQL_DECLARED_TABLE, CA_COMMIT) +then loop over monetdbe_column monetdbe_columns* {EB1, EBN} + convert EBi -> Bi + RBi = RMTput Bi + Add RBi to a list of remote BAT identifier ri_list. + sql_subtype tpe = getsqltype(Bi|EBi) + mvc_create_column(sql, t, columns[i].name, &tpe) + +voila a initialized sql_table* t object plust ri_list of remote BAT identifier. + +now pass t to sql_gencode.h:backend_create_remote_import(backend*be, sql_table*t) + +Which should have all information necessary to create the following function: + +local maken +function user.%temp(X1, ..., XN) + m:=sql.mvc(); + sql.append(m, "foo", "column1", X1); + . + . + . + sql.append(m, "foo", "columnn", Xn); + c := aggr.count(Xn); + sql.affectedRows(m, c); +end + +function user.%temp2() + remote.put() + +Register this function and remotely execute it: +remote.register(conn, user, %temp) +remote.exec(conn, user, %temp, RB1, ..., RBN) + +Now in case of a SQL REMOTE INSERT INTO statement: + +INSERT INTO R(foo) SELECT * FROM BAR; // ALLEEN AUTOMCOMMIT + +REL_INSERT(R(foo), REL(SELECT * FROM BAR)) + + +SELECT * FROM BAR +VALUES () ()) + + B1, ..., BN + +REL_INSERT(R(foo) + +function user.%temp(X1, ..., XN) + m:=sql.mvc(); + sql.append(m, "foo", "column1", X1); + . + . + . + sql.append(m, "foo", "columnn", Xn); + c := aggr.count(Xn); + sql.affectedRows(m, c); +end diff --git a/monetdb5/modules/mal/inspect.c b/monetdb5/modules/mal/inspect.c --- a/monetdb5/modules/mal/inspect.c +++ b/monetdb5/modules/mal/inspect.c @@ -311,6 +311,22 @@ INSPECTgetDefinition(Client cntxt, MalBl } static str +INSPECTgetExistence(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + (void) mb; + + bit *ret = getArgReference_bit(stk,pci,0); + str *mod = getArgReference_str(stk,pci,1); + str *fcn = getArgReference_str(stk,pci,2); + + Symbol s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn)); + + *ret = (s != NULL); + + return MAL_SUCCEED; +} + +static str INSPECTgetSignature(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { bat *ret = getArgReference_bat(stk,pci,0); @@ -667,6 +683,7 @@ INSPECTtypeName(Client cntxt, MalBlkPtr #include "mel.h" mel_func inspect_init_funcs[] = { pattern("inspect", "getDefinition", INSPECTgetDefinition, false, "Returns a string representation of a specific function.", args(1,3, batarg("",str),arg("mod",str),arg("fcn",str))), + pattern("inspect", "getExistence", INSPECTgetExistence, false, "Returns a boolean indicating existence of a definition of a specific function.", args(1,3, arg("",bit),arg("mod",str),arg("fcn",str))), pattern("inspect", "getSignature", INSPECTgetSignature, false, "Returns the function signature(s).", args(1,3, batarg("",str),arg("mod",str),arg("fcn",str))), pattern("inspect", "getComment", INSPECTgetComment, false, "Returns the function help information.", args(1,3, batarg("",str),arg("mod",str),arg("fcn",str))), pattern("inspect", "getSource", INSPECTgetSource, false, "Return the original input for a function.", args(1,3, arg("",str),arg("mod",str),arg("fcn",str))), 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 @@ -70,7 +70,6 @@ #ifdef HAVE_MAPI _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list