Changeset: 41911d3ea79a for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/41911d3ea79a
Modified Files:
sql/backends/monet5/rel_bin.c
sql/backends/monet5/sql_scenario.c
sql/server/rel_select.c
sql/server/rel_semantic.c
sql/server/sql_parser.y
Branch: default
Log Message:
add after a query an optional parameter list via : (p0, ... pn)
diffs (261 lines):
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -826,6 +826,41 @@ exp2bin_case(backend *be, sql_exp *fe, s
}
static stmt *
+exp2bin_named_placeholders(backend *be, sql_exp *fe)
+{
+ int argc = 0;
+ char arg[IDLENGTH];
+ list *args = fe->l;
+
+ if (list_empty(args))
+ return NULL;
+ for (node *n = args->h; n; n = n->next, argc++) {
+ sql_exp *a = n->data;
+ sql_subtype *t = exp_subtype(a);
+ stmt *s = exp_bin(be, a, NULL, NULL, NULL, NULL, NULL, NULL, 1,
0, 1);
+ InstrPtr q = newAssignment(be->mb);
+
+ if (!q || !t || !s) {
+ sql_error(be->mvc, 10, SQLSTATE(42000) MAL_MALLOC_FAIL);
+ return NULL;
+ }
+ int type = t->type->localtype, varid = 0;
+
+ snprintf(arg, IDLENGTH, "A%d", argc);
+ if ((varid = newVariable(be->mb, arg, strlen(arg), type)) < 0) {
+ sql_error(be->mvc, 10, SQLSTATE(42000) "Internal error while
compiling statement: variable id too long");
+ return NULL;
+ }
+ if (q)
+ getDestVar(q) = varid;
+ q = pushArgument(be->mb, q, s->nr);
+ pushInstruction(be->mb, q);
+ //setVarType(be->mb, varid, type);
+ }
+ return NULL;
+}
+
+static stmt *
exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt
*isel, int depth)
{
stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond =
NULL, *ocond = NULL, *cond = NULL;
@@ -1483,6 +1518,8 @@ exp_bin(backend *be, sql_exp *e, stmt *l
return exp2bin_copyfrombinary(be, e, left,
right, sel);
if (strcmp(fname, "file_loader") == 0)
return exp2bin_file_loader(be, e, left, right,
sel);
+ if (strcmp(fname, "-1") == 0) /* map arguments to A0 ..
An */
+ return exp2bin_named_placeholders(be, e);
}
if (!list_empty(exps)) {
unsigned nrcols = 0;
diff --git a/sql/backends/monet5/sql_scenario.c
b/sql/backends/monet5/sql_scenario.c
--- a/sql/backends/monet5/sql_scenario.c
+++ b/sql/backends/monet5/sql_scenario.c
@@ -1318,12 +1318,12 @@ SQLparser(Client c, backend *be)
be->vtop = oldvtop;
be->vid = oldvid;
(void)runtimeProfileSetTag(c); /* generate and set the tag in
the mal block of the clients current program. */
- if (m->emode != m_prepare) {
+ if (m->emode != m_prepare || (m->emode == m_prepare && (m->emod
& mod_exec) && is_ddl(r->op)) /* direct execution prepare */) {
scanner_query_processed(&(m->scanner));
err = 0;
setVarType(c->curprg->def, 0, 0);
- if (be->subbackend &&
be->subbackend->check(be->subbackend, r)) {
+ if (m->emode != m_prepare && be->subbackend &&
be->subbackend->check(be->subbackend, r)) {
res_table *rt = NULL;
if (be->subbackend->exec(be->subbackend, r,
be->result_id++, &rt) == NULL) { /* on error fall back */
if (rt) {
@@ -1337,7 +1337,19 @@ SQLparser(Client c, backend *be)
Tbegin = GDKusec();
int opt = 0;
- if (backend_dumpstmt(be, c->curprg->def, r, !(m->emod &
mod_exec), 0, c->query) < 0) {
+ if (m->emode == m_prepare && (m->emod & mod_exec)) {
+ /* generated the named parameters for the
placeholders */
+ if (backend_dumpstmt(be, c->curprg->def, r->r,
!(m->emod & mod_exec), 0, c->query) < 0) {
+ msg = handle_error(m, 0, msg);
+ err = 1;
+ MSresetInstructions(c->curprg->def,
oldstop);
+ freeVariables(c, c->curprg->def, NULL,
oldvtop, oldvid);
+ }
+ r = r->l;
+ m->emode = m_normal;
+ m->emod &= ~mod_exec;
+ }
+ if (!err && backend_dumpstmt(be, c->curprg->def, r,
!(m->emod & mod_exec), 0, c->query) < 0) {
msg = handle_error(m, 0, msg);
err = 1;
MSresetInstructions(c->curprg->def, oldstop);
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -3370,6 +3370,45 @@ rel_nop_(mvc *sql, sql_rel *rel, sql_exp
return exp_op4(sql->sa, a1,a2,a3,a4,f);
}
+static sql_func *
+inplace_func(mvc *sql, sql_rel *r)
+{
+ sql_func *f = SA_NEW(sql->sa, sql_func);
+ list *res = NULL;
+
+ if (r && is_project(r->op) && !list_empty(r->exps)) {
+ sql_arg *a;
+ node *m;
+
+ res = sa_list(sql->sa);
+ for(m = r->exps->h; m; m = m->next) {
+ sql_exp *e = m->data;
+ sql_subtype *t = exp_subtype(e);
+
+ a = NULL;
+ if (t)
+ a = sql_create_arg(sql->sa, NULL, t, ARG_OUT);
+ append(res, a);
+ }
+ }
+
+ *f = (sql_func) {
+ .mod = "",
+ .imp = "",
+ .type = F_PROC,
+ .lang = FUNC_LANG_INT,
+ .query = NULL,
+ .ops = sql->params,
+ .res = res,
+ };
+ base_init(sql->sa, &f->base, 0, true, NULL);
+ f->base.new = 1;
+ f->base.id = -1;
+ f->base.name = "-1";
+ f->instantiated = TRUE;
+ return f;
+}
+
static sql_exp *
rel_nop(sql_query *query, sql_rel **rel, symbol *se, int fs, exp_kind ek)
{
@@ -3400,15 +3439,16 @@ rel_nop(sql_query *query, sql_rel **rel,
if (err)
return NULL;
- if ((q = qc_find(sql->qc, nr))) {
+ if (nr == -1 || (q = qc_find(sql->qc, nr))) {
list *nexps = new_exp_list(sql->sa);
- sql_func *f = q->f;
+ sql_func *f = q?q->f:inplace_func(sql, query->last_rel);
+ list *ops = q?f->ops:sql->params;
tl = sa_list(sql->sa);
- if (list_length(f->ops) != list_length(exps))
- return sql_error(sql, 02, SQLSTATE(42000) "EXEC
called with wrong number of arguments: expected %d, got %d",
list_length(f->ops), list_length(exps));
- if (exps->h && f->ops) {
- for (node *n = exps->h, *m = f->ops->h; n && m;
n = n->next, m = m->next) {
+ if (list_length(ops) != list_length(exps))
+ return sql_error(sql, 02, SQLSTATE(42000) "EXEC
called with wrong number of arguments: expected %d, got %d", list_length(ops),
list_length(exps));
+ if (exps->h && ops) {
+ for (node *n = exps->h, *m = ops->h; n && m; n
= n->next, m = m->next) {
sql_arg *a = m->data;
sql_exp *e = n->data;
sql_subtype *ntp = &a->type;
@@ -3425,7 +3465,8 @@ rel_nop(sql_query *query, sql_rel **rel,
}
if (err)
return NULL;
- sql->type = q->type;
+ if (q)
+ sql->type = q->type;
return exp_op(sql->sa, list_empty(nexps) ? NULL :
nexps, sql_dup_subfunc(sql->sa, f, tl, NULL));
} else {
return sql_error(sql, 02, SQLSTATE(42000) "EXEC:
PREPARED Statement missing '%d'", nr);
diff --git a/sql/server/rel_semantic.c b/sql/server/rel_semantic.c
--- a/sql/server/rel_semantic.c
+++ b/sql/server/rel_semantic.c
@@ -207,6 +207,8 @@ rel_semantic(sql_query *query, symbol *s
r = rel_list(sql->sa, r, nr);
else
r = nr;
+ if (sql->emode == m_prepare)
+ query->last_rel = r;
}
stack_pop_frame(sql);
return r;
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -235,6 +235,7 @@ int yydebug=1;
drop_table_element
exec
exec_ref
+ arg_list_ref
existence_test
filter_exp
forest_element_value
@@ -814,7 +815,7 @@ sqlstmt:
{
(void)yynerrs;
if (m->sym) {
- append_symbol(m->sym->data.lval, $$);
+ append_symbol(m->sym->data.lval, $1);
$$ = m->sym;
} else {
m->sym = $$ = $1;
@@ -822,6 +823,26 @@ sqlstmt:
YYACCEPT;
}
+ | sql ':' arg_list_ref SCOLON
+ {
+ (void)yynerrs;
+ if (!m->emode) /* don't replace m_deps/instantiate */
+ m->emode = m_prepare;
+ if (m->sym) {
+ append_symbol(m->sym->data.lval, $1);
+ $$ = m->sym;
+ } else {
+ dlist* stmts = L();
+ append_symbol(stmts, $$ = $1);
+ m->sym = _symbol_create_list(SQL_MULSTMT, stmts);
+ }
+ if (m->sym->data.lval) {
+ m->emod |= mod_exec;
+ append_symbol(m->sym->data.lval,
_symbol_create_symbol(SQL_CALL, $3));
+ }
+ YYACCEPT;
+ }
+
| prepare {
if (!m->emode) /* don't replace m_deps/instantiate */
m->emode = m_prepare;
@@ -5854,17 +5875,21 @@ dealloc:
;
exec_ref:
- posint '(' ')'
+ posint arg_list_ref { $$ = $2; $$->data.lval->h->data.i_val = $1; }
+ ;
+
+arg_list_ref:
+ '(' ')'
{ dlist *l = L();
- append_int(l, $1);
+ append_int(l, -1);
append_int(l, FALSE); /* ignore distinct */
append_list(l, NULL);
$$ = _symbol_create_list( SQL_NOP, l ); }
-| posint '(' value_commalist ')'
+ | '(' value_commalist ')'
{ dlist *l = L();
- append_int(l, $1);
+ append_int(l, -1);
append_int(l, FALSE); /* ignore distinct */
- append_list(l, $3);
+ append_list(l, $2);
$$ = _symbol_create_list( SQL_NOP, l ); }
;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]