Changeset: 39b18f5656dc for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=39b18f5656dc
Modified Files:
monetdb5/mal/mal_interpreter.c
sql/backends/monet5/UDF/pyapi/pyloader.c
sql/backends/monet5/rel_bin.c
sql/backends/monet5/sql_statement.c
sql/server/rel_psm.c
sql/server/rel_select.c
sql/server/rel_select.h
sql/server/rel_updates.c
Branch: default
Log Message:
Make loader functions work with subqueries as input.
diffs (truncated from 320 to 300 lines):
diff --git a/monetdb5/mal/mal_interpreter.c b/monetdb5/mal/mal_interpreter.c
--- a/monetdb5/mal/mal_interpreter.c
+++ b/monetdb5/mal/mal_interpreter.c
@@ -665,7 +665,7 @@ str runMALsequence(Client cntxt, MalBlkP
}
break;
case CMDcall:
- ret =malCommandCall(stk, pci);
+ ret = malCommandCall(stk, pci);
#ifndef NDEBUG
/* check that the types of actual results match
* expected results */
diff --git a/sql/backends/monet5/UDF/pyapi/pyloader.c
b/sql/backends/monet5/UDF/pyapi/pyloader.c
--- a/sql/backends/monet5/UDF/pyapi/pyloader.c
+++ b/sql/backends/monet5/UDF/pyapi/pyloader.c
@@ -105,22 +105,39 @@ PYFUNCNAME(PyAPIevalLoader)(Client cntxt
argnode = sqlfun && sqlfun->ops->cnt > 0 ? sqlfun->ops->h : NULL;
for (i = pci->retc + 2; i < argcount; i++) {
PyInput inp;
+ inp.bat = NULL;
+ inp.sql_subtype = NULL;
PyObject *val = NULL;
- if (isaBatType(getArgType(mb, pci, i))) {
- msg = createException(MAL, "pyapi.eval_loader",
- "Only scalar
arguments are supported.");
- goto wrapup;
+ if (!isaBatType(getArgType(mb, pci, i))) {
+ inp.scalar = true;
+ inp.bat_type = getArgType(mb, pci, i);
+ inp.count = 1;
+ if (inp.bat_type == TYPE_str) {
+ inp.dataptr = getArgReference_str(stk, pci, i);
+ } else {
+ inp.dataptr = getArgReference(stk, pci, i);
+ }
+ val = PyArrayObject_FromScalar(&inp, &msg);
+ } else {
+ BAT* b = BATdescriptor(*getArgReference_bat(stk, pci,
i));
+ if (b == NULL) {
+ msg = createException(
+ MAL, "pyapi.eval",
+ "The BAT passed to the function
(argument #%d) is NULL.\n",
+ i - (pci->retc + 2) + 1);
+ goto wrapup;
+ }
+ inp.scalar = false;
+ inp.count = BATcount(b);
+ inp.bat_type = ATOMstorage(getBatType(getArgType(mb,
pci, i)));
+ inp.bat = b;
+
+ val = PyMaskedArray_FromBAT(
+ &inp, 0, inp.count, &msg,
+ false);
+ BBPunfix(inp.bat->batCacheid);
}
- inp.scalar = true;
- inp.bat_type = getArgType(mb, pci, i);
- inp.count = 1;
- if (inp.bat_type == TYPE_str) {
- inp.dataptr = getArgReference_str(stk, pci, i);
- } else {
- inp.dataptr = getArgReference(stk, pci, i);
- }
- val = PyArrayObject_FromScalar(&inp, &msg);
if (msg != MAL_SUCCEED) {
goto wrapup;
}
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
@@ -436,7 +436,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l
if (!es)
return NULL;
- if (rows && en == exps->h)
+ if (rows && en == exps->h && f->func->type !=
F_LOADER)
es = stmt_const(be, rows, es);
if (es->nrcols > nrcols)
nrcols = es->nrcols;
@@ -1417,34 +1417,36 @@ rel2bin_table(backend *be, sql_rel *rel,
return NULL;
}
l = sa_list(sql->sa);
- if (f->func->varres) {
- for(i=0, en = rel->exps->h, n = f->res->h; en; en =
en->next, n = n->next, i++ ) {
- sql_exp *exp = en->data;
- sql_subtype *st = n->data;
- const char *rnme = exp->rname?exp->rname:exp->l;
- stmt *s = stmt_rs_column(be, psub, i, st);
-
- s = stmt_alias(be, s, rnme, exp->name);
- list_append(l, s);
- }
- } else {
- for(i = 0, n = f->func->res->h; n; n = n->next, i++ ) {
- sql_arg *a = n->data;
- stmt *s = stmt_rs_column(be, psub, i,
&a->type);
- const char *rnme = exp_find_rel_name(op);
-
- s = stmt_alias(be, s, rnme, a->name);
- list_append(l, s);
- }
- if (list_length(f->res) == list_length(f->func->res) +
1) {
- /* add missing %TID% column */
- sql_subtype *t = f->res->t->data;
- stmt *s = stmt_rs_column(be, psub, i, t);
- const char *rnme = exp_find_rel_name(op);
-
- s = stmt_alias(be, s, rnme, TID);
- list_append(l, s);
- }
+ if (f->func->res) {
+ if (f->func->varres) {
+ for(i=0, en = rel->exps->h, n =
f->res->h; en; en = en->next, n = n->next, i++ ) {
+ sql_exp *exp = en->data;
+ sql_subtype *st = n->data;
+ const char *rnme =
exp->rname?exp->rname:exp->l;
+ stmt *s = stmt_rs_column(be,
psub, i, st);
+
+ s = stmt_alias(be, s, rnme,
exp->name);
+ list_append(l, s);
+ }
+ } else {
+ for(i = 0, n = f->func->res->h; n; n =
n->next, i++ ) {
+ sql_arg *a = n->data;
+ stmt *s = stmt_rs_column(be,
psub, i, &a->type);
+ const char *rnme =
exp_find_rel_name(op);
+
+ s = stmt_alias(be, s, rnme,
a->name);
+ list_append(l, s);
+ }
+ if (list_length(f->res) ==
list_length(f->func->res) + 1) {
+ /* add missing %TID% column */
+ sql_subtype *t =
f->res->t->data;
+ stmt *s = stmt_rs_column(be,
psub, i, t);
+ const char *rnme =
exp_find_rel_name(op);
+
+ s = stmt_alias(be, s, rnme,
TID);
+ list_append(l, s);
+ }
+ }
}
if (!rel->flag && sub && sub->nrcols) {
assert(0);
diff --git a/sql/backends/monet5/sql_statement.c
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -2591,7 +2591,7 @@ stmt_Nop(backend *be, stmt *ops, sql_sub
return NULL;
mod = sql_func_mod(f->func);
fimp = sql_func_imp(f->func);
- if (o && o->nrcols > 0) {
+ if (o && o->nrcols > 0 && f->func->type != F_LOADER) {
sql_subtype *res = f->res->h->data;
fimp = convertMultiplexFcn(fimp);
q = NULL;
diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -1339,14 +1339,12 @@ psm_analyze(mvc *sql, char *analyzeType,
}
static sql_rel*
-create_table_from_loader(mvc *sql, dlist *qname, symbol *fcall)
-{
+create_table_from_loader(mvc *sql, dlist *qname, symbol *fcall) {
sql_schema *s = NULL;
char *sname = qname_schema(qname);
char *tname = qname_table(qname);
- sql_exp *import = NULL;
- exp_kind ek = {type_value, card_loader, FALSE};
- sql_rel *res = NULL;
+ sql_subfunc *loader = NULL;
+ sql_rel* rel = NULL;
if (sname && !(s = mvc_bind_schema(sql, sname)))
return sql_error(sql, 02, "3F000!CREATE TABLE: no such schema
'%s'", sname);
@@ -1357,17 +1355,18 @@ create_table_from_loader(mvc *sql, dlist
return sql_error(sql, 02, "42000!CREATE TABLE: insufficient
privileges for user '%s' in schema '%s'", stack_get_string(sql,
"current_user"), s->base.name);
}
- import = rel_value_exp(sql, &res, fcall, sql_sel, ek);
- if (!import) {
+ rel = rel_loader_function(sql, fcall, &loader);
+ if (!rel || !loader) {
return NULL;
}
- ((sql_subfunc*) import->f)->sname = sname ? sa_zalloc(sql->sa,
strlen(sname) + 1) : NULL;
- ((sql_subfunc*) import->f)->tname = tname ? sa_zalloc(sql->sa,
strlen(tname) + 1) : NULL;
+ loader->sname = sname ? sa_zalloc(sql->sa, strlen(sname) + 1) : NULL;
+ loader->tname = tname ? sa_zalloc(sql->sa, strlen(tname) + 1) : NULL;
- if (sname) strcpy(((sql_subfunc*) import->f)->sname, sname);
- if (tname) strcpy(((sql_subfunc*) import->f)->tname, tname);
+ if (sname) strcpy(loader->sname, sname);
+ if (tname) strcpy(loader->tname, tname);
- return rel_psm_stmt(sql->sa, import);
+
+ return rel;
}
sql_rel *
@@ -1423,8 +1422,8 @@ rel_psm(mvc *sql, symbol *s)
dlist *qname = l->h->data.lval;
symbol *sym = l->h->next->data.sym;
- ret = create_table_from_loader(sql, qname, sym);
- sql->type = Q_UPDATE;
+ ret = rel_psm_stmt(sql->sa, exp_rel(sql,
create_table_from_loader(sql, qname, sym)));
+ sql->type = Q_SCHEMA;
} break;
case SQL_CREATE_TRIGGER:
{
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
@@ -5415,3 +5415,70 @@ schema_selects(mvc *sql, sql_schema *sch
return res;
}
+sql_rel *
+rel_loader_function(mvc* sql, symbol* fcall, sql_subfunc **loader_function) {
+ list *exps = NULL, *tl;
+ exp_kind ek = { type_value, card_relation, TRUE };
+ sql_rel *sq = NULL;
+ sql_exp *e = NULL;
+ symbol *sym = fcall;
+ dnode *l = sym->data.lval->h;
+ char *sname = qname_schema(l->data.lval);
+ char *fname = qname_fname(l->data.lval);
+ char *tname = NULL;
+ node *en;
+ sql_schema *s = sql->session->schema;
+ sql_subfunc* sf;
+
+ tl = sa_list(sql->sa);
+ exps = new_exp_list(sql->sa);
+ if (l->next) { /* table call with subquery */
+ if (l->next->type == type_symbol && l->next->data.sym->token ==
SQL_SELECT) {
+ if (l->next->next != NULL)
+ return sql_error(sql, 02, "SELECT: '%s'
requires a single sub query", fname);
+ sq = rel_subquery(sql, NULL, l->next->data.sym, ek, 0
/*apply*/);
+ } else if (l->next->type == type_symbol || l->next->type ==
type_list) {
+ dnode *n;
+ exp_kind iek = {type_value, card_column, TRUE};
+ list *exps = sa_list (sql->sa);
+
+ if (l->next->type == type_symbol)
+ n = l->next;
+ else
+ n = l->next->data.lval->h;
+ for ( ; n; n = n->next) {
+ sql_exp *e = rel_value_exp(sql, NULL,
n->data.sym, sql_sel, iek);
+
+ if (!e)
+ return NULL;
+ append(exps, e);
+ }
+ sq = rel_project(sql->sa, NULL, exps);
+ }
+
+ /* reset error */
+ sql->session->status = 0;
+ sql->errstr[0] = '\0';
+ if (!sq)
+ return sql_error(sql, 02, "SELECT: no such operator
'%s'", fname);
+ for (en = sq->exps->h; en; en = en->next) {
+ sql_exp *e = en->data;
+
+ append(exps, e=exp_alias_or_copy(sql, tname,
exp_name(e), NULL, e));
+ append(tl, exp_subtype(e));
+ }
+ }
+ if (sname)
+ s = mvc_bind_schema(sql, sname);
+ sf = bind_func_(sql, s, fname, tl, F_LOADER);
+ if (!sf)
+ return sql_error(sql, 02, "SELECT: no such operator '%s'",
fname);
+ e = exp_op(sql->sa, exps, sf);
+
+ if (loader_function) {
+ *loader_function = sf;
+ }
+
+ return rel_table_func(sql->sa, sq, e, new_exp_list(sql->sa), (sq !=
NULL));
+}
+
diff --git a/sql/server/rel_select.h b/sql/server/rel_select.h
--- a/sql/server/rel_select.h
+++ b/sql/server/rel_select.h
@@ -31,4 +31,7 @@ extern sql_exp *rel_nop_(mvc *sql, sql_e
extern sql_rel *rel_with_query(mvc *sql, symbol *q);
extern sql_rel *table_ref(mvc *sql, sql_rel *rel, symbol *tableref, int
lateral);
+
+extern sql_rel *rel_loader_function(mvc* sql, symbol* s, sql_subfunc
**loader_function);
+
#endif /*_REL_SELECT_H_*/
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list