str SQLengineIntern(Client c, backend *be) { str msg = MAL_SUCCEED; MalStkPtr oldglb = c->glb; char oldlang = be->language; mvc *m = be->mvc; InstrPtr p; MalBlkPtr mb; if (oldlang == 'X') { /* return directly from X-commands */ sqlcleanup(be->mvc, 0); return MAL_SUCCEED; } if (m->emod & mod_explain) { if (be->q && be->q->code) printFunction(c->fdout, ((Symbol) (be->q->code))->def, 0, LIST_MAL_NAME | LIST_MAL_VALUE | LIST_MAL_MAPI); else if (be->q) msg = createException(PARSE, "SQLparser", "%s", (*m->errstr) ? m->errstr : "39000!program contains errors"); else if (c->curprg->def) printFunction(c->fdout, c->curprg->def, 0, LIST_MAL_NAME | LIST_MAL_VALUE | LIST_MAL_MAPI); goto cleanup_engine; } if (m->emod & mod_dot) { if (be->q && be->q->code) showFlowGraph(((Symbol) (be->q->code))->def, 0, "stdout-mapi"); else if (be->q) msg = createException(PARSE, "SQLparser", "%s", (*m->errstr) ? m->errstr : "39000!program contains errors"); else if (c->curprg->def) showFlowGraph(c->curprg->def, 0, "stdout-mapi"); goto cleanup_engine; } #ifdef SQL_SCENARIO_DEBUG mnstr_printf(GDKout, "#Ready to execute SQL statement\n"); #endif if (c->curprg->def->stop == 1) { sqlcleanup(be->mvc, 0); return MAL_SUCCEED; } if (m->emode == m_inplace) { msg = SQLexecutePrepared(c, be, be->q); goto cleanup_engine; } if (m->emode == m_prepare) goto cleanup_engine; assert(c->glb == 0 || c->glb == oldglb); /* detect leak */ c->glb = 0; be->language = 'D'; /* * The code below is copied from MALengine, which handles execution * in the context of a user global environment. We have a private * environment. */ if (MALcommentsOnly(c->curprg->def)) { msg = MAL_SUCCEED; } else { msg = (str) runMAL(c, c->curprg->def, 0, 0); } cleanup_engine: if (m->type == Q_SCHEMA) qc_clean(m->qc); if (msg) { enum malexception type = getExceptionType(msg); if (type == OPTIMIZER) { MSresetInstructions(c->curprg->def, 1); freeVariables(c, c->curprg->def, NULL, be->vtop); be->language = oldlang; assert(c->glb == 0 || c->glb == oldglb); /* detect leak */ c->glb = oldglb; if ( msg) GDKfree(msg); return SQLrecompile(c, be); // retry compilation } else { /* don't print exception decoration, just the message */ char *n = NULL; char *o = msg; while ((n = strchr(o, '\n')) != NULL) { *n = '\0'; mnstr_printf(c->fdout, "!%s\n", getExceptionMessage(o)); *n++ = '\n'; o = n; } if (*o != 0) mnstr_printf(c->fdout, "!%s\n", getExceptionMessage(o)); } showErrors(c); m->session->status = -10; } mb = c->curprg->def; if (m->type != Q_SCHEMA && be->q && msg) { qc_delete(m->qc, be->q); } else if (m->type != Q_SCHEMA && be->q && mb && varGetProp(mb, getArg(p = getInstrPtr(mb, 0), 0), runonceProp)) { msg = SQLCacheRemove(c, getFunctionId(p)); qc_delete(be->mvc->qc, be->q); ///* this should invalidate any match */ //be->q->key= -1; //be->q->paramlen = -1; ///* qc_delete(be->q) */ } be->q = NULL; sqlcleanup(be->mvc, (!msg) ? 0 : -1); MSresetInstructions(c->curprg->def, 1); freeVariables(c, c->curprg->def, NULL, be->vtop); be->language = oldlang; /* * Any error encountered during execution should block further processing * unless auto_commit has been set. */ assert(c->glb == 0 || c->glb == oldglb); /* detect leak */ c->glb = oldglb; return msg; }
str MALengine(Client c) { Symbol prg; str msg = MAL_SUCCEED; MalBlkRecord oldstate = *c->curprg->def; oldstate.stop = 0; if (c->blkmode) return MAL_SUCCEED; prg = c->curprg; if (prg == NULL) throw(SYNTAX, "mal.engine", SYNTAX_SIGNATURE); if (prg->def == NULL) throw(SYNTAX, "mal.engine", SYNTAX_SIGNATURE); if (prg->def->errors > 0) { showErrors(c); if (c->listing) printFunction(c->fdout, c->curprg->def, 0, c->listing); MSresetVariables(c, c->curprg->def, c->glb, oldstate.vtop); resetMalBlk(c->curprg->def, 1); throw(MAL, "mal.engine", PROGRAM_GENERAL); } if (prg->def->stop == 1 || MALcommentsOnly(prg->def)) return 0; /* empty block */ if (c->glb) { if (prg->def && c->glb->stksize < prg->def->vsize){ c->glb = reallocGlobalStack(c->glb, prg->def->vsize); if( c->glb == NULL) throw(MAL, "mal.engine", MAL_MALLOC_FAIL); } c->glb->stktop = prg->def->vtop; c->glb->blk = prg->def; c->glb->cmd = (c->itrace && c->itrace != 'C') ? 'n' : 0; } if (c->listing > 1) printFunction(c->fdout, c->curprg->def, 0, c->listing); /* * In interactive mode we should avoid early garbage collection of values. * This can be controlled by the clean up control at the instruction level * and marking all non-temporary variables as being (potentially) used. */ if (c->glb) { c->glb->pcup = 0; c->glb->keepAlive = TRUE; /* no garbage collection */ } if (prg->def->errors == 0) msg = (str) runMAL(c, prg->def, 0, c->glb); if (msg) { /* ignore "internal" exceptions */ str fcn = getExceptionPlace(msg); /* retrieves from "first" exception */ if (strcmp(fcn, "client.quit") != 0) dumpExceptionsToStream(c->fdout, msg); GDKfree(fcn); if (!c->listing) printFunction(c->fdout, c->curprg->def, 0, c->listing); showErrors(c); } MSresetVariables(c, prg->def, c->glb, 0); resetMalBlk(prg->def, 1); if (c->glb) { /* for global stacks avoid reinitialization from this point */ c->glb->stkbot = prg->def->vtop; } prg->def->errors = 0; if (c->itrace) mnstr_printf(c->fdout, "mdb>#EOD\n"); return msg; }