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
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to