/* * Determine the variables being used and clear non-used onces. */ void MSresetVariables(Client cntxt, MalBlkPtr mb, MalStkPtr glb, int start) { int i; bit *used = GDKzalloc(mb->vtop * sizeof(bit)); if( used == NULL){ GDKerror("MSresetVariables" MAL_MALLOC_FAIL); return; } for (i = 0; i < start && start < mb->vtop; i++) used[i] = 1; if (mb->errors == 0) for (i = start; i < mb->vtop; i++) { if (used[i] || !isTmpVar(mb, i)) { assert(!mb->var[i]->value.vtype || isVarConstant(mb, i)); used[i] = 1; } if (glb && !used[i]) { if (isVarConstant(mb, i)) garbageElement(cntxt, &glb->stk[i]); /* clean stack entry */ glb->stk[i].vtype = TYPE_int; glb->stk[i].len = 0; glb->stk[i].val.pval = 0; } } if (mb->errors == 0) trimMalVariables_(mb, used, glb); GDKfree(used); }
/* * Execution of the SQL program is delegated to the MALengine. * Different cases should be distinguished. The default is to * hand over the MAL block derived by the parser for execution. * However, when we received an Execute call, we make a shortcut * and prepare the stack for immediate execution */ str SQLexecutePrepared(Client c, backend *be, cq *q) { mvc *m = be->mvc; int argc, parc; ValPtr *argv, argvbuffer[MAXARG], v; ValRecord *argrec, argrecbuffer[MAXARG]; MalBlkPtr mb; MalStkPtr glb; InstrPtr pci; int i; str ret; Symbol qcode = q->code; if (!qcode || qcode->def->errors) { if (!qcode && *m->errstr) return createException(PARSE, "SQLparser", "%s", m->errstr); throw(SQL, "SQLengine", "39000!program contains errors"); } mb = qcode->def; pci = getInstrPtr(mb, 0); if (pci->argc >= MAXARG) argv = (ValPtr *) GDKmalloc(sizeof(ValPtr) * pci->argc); else argv = argvbuffer; if (pci->retc >= MAXARG) argrec = (ValRecord *) GDKmalloc(sizeof(ValRecord) * pci->retc); else argrec = argrecbuffer; /* prepare the target variables */ for (i = 0; i < pci->retc; i++) { argv[i] = argrec + i; argv[i]->vtype = getVarGDKType(mb, i); } argc = m->argc; parc = q->paramlen; if (argc != parc) { if (pci->argc >= MAXARG) GDKfree(argv); if (pci->retc >= MAXARG) GDKfree(argrec); throw(SQL, "sql.prepare", "07001!EXEC: wrong number of arguments for prepared statement: %d, expected %d", argc, parc); } else { for (i = 0; i < m->argc; i++) { atom *arg = m->args[i]; sql_subtype *pt = q->params + i; if (!atom_cast(arg, pt)) { /*sql_error(c, 003, buf); */ if (pci->argc >= MAXARG) GDKfree(argv); if (pci->retc >= MAXARG) GDKfree(argrec); throw(SQL, "sql.prepare", "07001!EXEC: wrong type for argument %d of " "prepared statement: %s, expected %s", i + 1, atom_type(arg)->type->sqlname, pt->type->sqlname); } argv[pci->retc + i] = &arg->data; } } glb = (MalStkPtr) (q->stk); ret = callMAL(c, mb, &glb, argv, (m->emod & mod_debug ? 'n' : 0)); /* cleanup the arguments */ for (i = pci->retc; i < pci->argc; i++) { garbageElement(c, v = &glb->stk[pci->argv[i]]); v->vtype = TYPE_int; v->val.ival = int_nil; } if (glb && ret) /* error */ garbageCollector(c, mb, glb, glb != 0); q->stk = (backend_stack) glb; if (glb && SQLdebug & 1) printStack(GDKstdout, mb, glb); if (pci->argc >= MAXARG) GDKfree(argv); if (pci->retc >= MAXARG) GDKfree(argrec); return ret; }