Changeset: fb02f301830a for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=fb02f301830a Added Files: MonetDB5/ChangeLog MonetDB5/mal/mal_session.c MonetDB5/modules/kernel/group.c MonetDB5/modules/kernel/group.h MonetDB5/modules/kernel/group.mal Modified Files: MonetDB5/modules/kernel/algebra.c MonetDB5/modules/kernel/algebra.h MonetDB5/modules/kernel/algebra.mal clients/Tests/MAL-signatures.stable.out clients/Tests/MAL-signatures.stable.out.int128 clients/Tests/exports.stable.out common/utils/msabaoth.c common/utils/msabaoth.h gdk/gdk_join.c gdk/gdk_select.c gdk/gdk_utils.c sql/backends/monet5/rel_bin.c sql/server/rel_exp.c sql/server/rel_optimizer.c sql/server/rel_unnest.c sql/test/BugTracker-2017/Tests/complicated_logic.Bug-105.stable.out tools/merovingian/client/monetdb.c tools/merovingian/daemon/client.c tools/merovingian/daemon/controlrunner.c tools/merovingian/daemon/discoveryrunner.c tools/merovingian/daemon/forkmserver.c tools/merovingian/daemon/forkmserver.h tools/merovingian/utils/database.c Branch: gdk-tracer Log Message:
Merge branch 'branches/default' into branches/gdk-tracer diffs (truncated from 2968 to 300 lines): diff --git a/MonetDB5/ChangeLog b/MonetDB5/ChangeLog new file mode 100644 --- /dev/null +++ b/MonetDB5/ChangeLog @@ -0,0 +1,10 @@ +# ChangeLog file for MonetDB5 +# This file is updated with Maddlog + +* Wed Nov 13 2019 Sjoerd Mullender <sjo...@acm.org> +- There are now versions of group.(sub)group(done) that produce a single + output containing just the groups. +- algebra.join and algebra.leftjoin now have forms which return a single + column. The column that is returned is the left column of the two + column version. + diff --git a/MonetDB5/mal/mal_session.c b/MonetDB5/mal/mal_session.c new file mode 100644 --- /dev/null +++ b/MonetDB5/mal/mal_session.c @@ -0,0 +1,737 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. + */ + +/* (author) M.L. Kersten + */ +#include "monetdb_config.h" +#include "mal_session.h" +#include "mal_instruction.h" /* for pushEndInstruction() */ +#include "mal_interpreter.h" /* for runMAL(), garbageElement() */ +#include "mal_parser.h" /* for parseMAL() */ +#include "mal_namespace.h" +#include "mal_authorize.h" +#include "mal_builder.h" +#include "msabaoth.h" +#include "mal_private.h" +#include "gdk.h" /* for opendir and friends */ +#include "gdk_tracer.h" + +/* + * The MonetDB server uses a startup script to boot the system. + * This script is an ordinary MAL program, but will mostly + * consist of include statements to load modules of general interest. + * The startup script is run as user Admin. + */ +str +malBootstrap(void) +{ + Client c; + str msg = MAL_SUCCEED; + str bootfile = "mal_init"; + + c = MCinitClient((oid) 0, NULL, NULL); + if(c == NULL) { + throw(MAL, "malBootstrap", "Failed to initialize client"); + } + assert(c != NULL); + c->curmodule = c->usermodule = userModule(); + if(c->usermodule == NULL) { + MCfreeClient(c); + throw(MAL, "malBootstrap", "Failed to initialize client MAL module"); + } + if ( (msg = defaultScenario(c)) ) { + MCfreeClient(c); + return msg; + } + if((msg = MSinitClientPrg(c, "user", "main")) != MAL_SUCCEED) { + MCfreeClient(c); + return msg; + } + if( MCinitClientThread(c) < 0){ + MCfreeClient(c); + throw(MAL, "malBootstrap", "Failed to create client thread"); + } + if ((msg = malInclude(c, bootfile, 0)) != MAL_SUCCEED) { + MCfreeClient(c); + return msg; + } + pushEndInstruction(c->curprg->def); + chkProgram(c->usermodule, c->curprg->def); + if ( (msg= c->curprg->def->errors) != MAL_SUCCEED ) { + MCfreeClient(c); + return msg; + } + msg = MALengine(c); + MCfreeClient(c); + return msg; +} + +/* + * Every client has a 'main' function to collect the statements. Once + * the END instruction has been found, it is added to the symbol table + * and a fresh container is being constructed. Note, this scheme makes + * testing for recursive function calls a little more difficult. + * Therefore, type checking should be performed afterwards. + * + * In interactive mode, the closing statement is never reached. The + * 'main' procedure is typically cleaned between successive external + * messages except for its variables, which are considerd global. This + * storage container is re-used when during the previous call nothing + * was added. At the end of the session we have to garbage collect the + * BATs introduced. + */ +static str +MSresetClientPrg(Client cntxt, str mod, str fcn) +{ + MalBlkPtr mb; + InstrPtr p; + + cntxt->itrace = 0; /* turn off any debugging */ + mb = cntxt->curprg->def; + mb->stop = 1; + mb->errors = MAL_SUCCEED; + p = mb->stmt[0]; + + p->gc = 0; + p->retc = 1; + p->argc = 1; + p->argv[0] = 0; + + /* CHECK */ + // nme variable is missing? + // DEBUG(MAL_SESSION, "Reset sym '%s %s' to '%s', id %d\n", cntxt->curprg->name, getFunctionId(p), nme, findVariable(mb, nme)); + + DEBUG(MAL_SESSION, "vtop: %d\n", mb->vtop); + if( mb->vtop) + DEBUG(MAL_SESSION, "First variable: %s\n", mb->var[0].id); + + setModuleId(p, mod); + setFunctionId(p, fcn); + if( findVariable(mb,fcn) < 0) + p->argv[0] = newVariable(mb, fcn, strlen(fcn), TYPE_void); + + setVarType(mb, findVariable(mb, fcn), TYPE_void); + /* remove any MAL history */ + if (mb->history) { + freeMalBlk(mb->history); + mb->history = 0; + } + return MAL_SUCCEED; +} + +/* + * Create a new container block + */ + +str +MSinitClientPrg(Client cntxt, str mod, str nme) +{ + int idx; + + if (cntxt->curprg && idcmp(nme, cntxt->curprg->name) == 0) + return MSresetClientPrg(cntxt, putName(mod), putName(nme)); + cntxt->curprg = newFunction(putName(mod), putName(nme), FUNCTIONsymbol); + if( cntxt->curprg == 0) + throw(MAL, "initClientPrg", SQLSTATE(HY001) MAL_MALLOC_FAIL); + if( (idx= findVariable(cntxt->curprg->def,"main")) >=0) + setVarType(cntxt->curprg->def, idx, TYPE_void); + insertSymbol(cntxt->usermodule,cntxt->curprg); + + if (cntxt->glb == NULL ) + cntxt->glb = newGlobalStack(MAXGLOBALS + cntxt->curprg->def->vsize); + if( cntxt->glb == NULL) + throw(MAL,"initClientPrg", SQLSTATE(HY001) MAL_MALLOC_FAIL); + assert(cntxt->curprg->def != NULL); + assert(cntxt->curprg->def->vtop >0); + return MAL_SUCCEED; +} + +/* + * The default method to interact with the database server is to connect + * using a port number. The first line received should contain + * authorization information, such as user name. + * + * The scheduleClient receives a challenge response consisting of + * endian:user:password:lang:database: + */ +static void +exit_streams( bstream *fin, stream *fout ) +{ + if (fout && fout != GDKstdout) { + mnstr_flush(fout); + close_stream(fout); + } + if (fin) + bstream_destroy(fin); +} + +const char* mal_enableflag = "mal_for_all"; + +void +MSscheduleClient(str command, str challenge, bstream *fin, stream *fout, protocol_version protocol, size_t blocksize) +{ + char *user = command, *algo = NULL, *passwd = NULL, *lang = NULL; + char *database = NULL, *s; + const char *dbname; + str msg = MAL_SUCCEED; + bool filetrans = false; + Client c; + + /* decode BIG/LIT:user:{cypher}passwordchal:lang:database: line */ + + /* byte order */ + s = strchr(user, ':'); + if (s) { + *s = 0; + mnstr_set_bigendian(fin->s, strcmp(user, "BIG") == 0); + user = s + 1; + } else { + mnstr_printf(fout, "!incomplete challenge '%s'\n", user); + exit_streams(fin, fout); + GDKfree(command); + return; + } + + /* passwd */ + s = strchr(user, ':'); + if (s) { + *s = 0; + passwd = s + 1; + /* decode algorithm, i.e. {plain}mypasswordchallenge */ + if (*passwd != '{') { + mnstr_printf(fout, "!invalid password entry\n"); + exit_streams(fin, fout); + GDKfree(command); + return; + } + algo = passwd + 1; + s = strchr(algo, '}'); + if (!s) { + mnstr_printf(fout, "!invalid password entry\n"); + exit_streams(fin, fout); + GDKfree(command); + return; + } + *s = 0; + passwd = s + 1; + } else { + mnstr_printf(fout, "!incomplete challenge '%s'\n", user); + exit_streams(fin, fout); + GDKfree(command); + return; + } + + /* lang */ + s = strchr(passwd, ':'); + if (s) { + *s = 0; + lang = s + 1; + } else { + mnstr_printf(fout, "!incomplete challenge, missing language\n"); + exit_streams(fin, fout); + GDKfree(command); + return; + } + + /* database */ + s = strchr(lang, ':'); + if (s) { + *s = 0; + database = s + 1; + /* we can have stuff following, make it void */ + s = strchr(database, ':'); + if (s) + *s++ = 0; + } + + if (s && strncmp(s, "FILETRANS:", 10) == 0) { + s += 10; + filetrans = true; + } + + dbname = GDKgetenv("gdk_dbname"); + if (database != NULL && database[0] != '\0' && + strcmp(database, dbname) != 0) + { + mnstr_printf(fout, "!request for database '%s', " + "but this is database '%s', " + "did you mean to connect to monetdbd instead?\n", + database, dbname); + /* flush the error to the client, and abort further execution */ + exit_streams(fin, fout); + GDKfree(command); + return; + } else { + str err; + oid uid; + sabdb *stats = NULL; + + /* access control: verify the credentials supplied by the user, + * no need to check for database stuff, because that is done per + * database itself (one gets a redirect) */ + err = AUTHcheckCredentials(&uid, NULL, user, passwd, challenge, algo); + if (err != MAL_SUCCEED) { + mnstr_printf(fout, "!%s\n", err); + exit_streams(fin, fout); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list