Changeset: 99bb3a0d5007 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=99bb3a0d5007
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql_gencode.c
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
        sql/include/sql_relation.h
        sql/server/rel_distribute.c
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/rel_psm.c
        sql/server/rel_semantic.c
        sql/server/sql_mvc.h
        sql/server/sql_parser.h
        sql/server/sql_parser.y
        sql/server/sql_scan.c
Branch: trails
Log Message:

First steps to use MAL factories in SQL UDFs. Added YIELD statements in the SQL 
UDF body, hence the UDF will be compiled into a MAL factory instead of a MAL 
function. For every call, the MAL stack will stop in the next YIELD statement. 
Later the next UDF call execution will start from this pointer rather in the 
beginning. This feature will be important to implement continuous UDFs.


diffs (truncated from 466 to 300 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
@@ -319,7 +319,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                                return stmt_vars(be, e->name, e->f, 1, 
GET_PSM_LEVEL(e->flag));
                        else
                                return stmt_var(be, e->name, &e->tpe, 1, 
GET_PSM_LEVEL(e->flag));
-               } else if (e->flag & PSM_RETURN) {
+               } else if (e->flag & PSM_RETURN || e->flag & PSM_YIELD) {
                        sql_exp *l = e->l;
                        stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, 
sel);
 
@@ -337,7 +337,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                                if (r->type == st_list)
                                        r = stmt_table(be, r, 1);
                        }
-                       return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
+                       return stmt_return(be, r, GET_PSM_LEVEL(e->flag), 
e->flag);
                } else if (e->flag & PSM_WHILE) {
                        /* while is a if - block true with leave statement
                         * needed because the condition needs to be inside this 
outer block */
diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -154,7 +154,7 @@ static int
        r = rel_optimizer(m, rel);
 
        backup = c->curprg;
-       curPrg = c->curprg = newFunction(putName(mod), putName(name), 
FUNCTIONsymbol);
+       curPrg = c->curprg = newFunction(putName(mod), putName(name), 
m->is_factory ? FACTORYsymbol : FUNCTIONsymbol);
        if( curPrg == NULL)
                return -1;
 
@@ -272,7 +272,7 @@ static int
 
        /* create stub */
        backup = c->curprg;
-       c->curprg = newFunction(putName(mod), putName(name), FUNCTIONsymbol);
+       c->curprg = newFunction(putName(mod), putName(name), m->is_factory ? 
FACTORYsymbol : FUNCTIONsymbol);
        if( c->curprg == NULL)
                return -1;
        lname[0] = 'l';
@@ -890,7 +890,7 @@ backend_create_sql_func(backend *be, sql
        assert(r);
 
        backup = c->curprg;
-       curPrg = c->curprg = newFunction(userRef, putName(f->base.name), 
FUNCTIONsymbol);
+       curPrg = c->curprg = newFunction(userRef, putName(f->base.name), 
m->is_factory? FACTORYsymbol : FUNCTIONsymbol);
        if( curPrg == NULL)
                goto cleanup;
 
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
@@ -3319,7 +3319,7 @@ dump_cols(MalBlkPtr mb, list *l, InstrPt
 }
 
 stmt *
-stmt_return(backend *be, stmt *val, int nr_declared_tables)
+stmt_return(backend *be, stmt *val, int nr_declared_tables, int flag) /* also 
used for yield statements */
 {
        MalBlkPtr mb = be->mb;
        InstrPtr q = NULL;
@@ -3333,7 +3333,7 @@ stmt_return(backend *be, stmt *val, int 
        q = newInstruction(mb, NULL, NULL);
        if (q == NULL)
                return NULL;
-       q->barrier= RETURNsymbol;
+       q->barrier = ((flag & PSM_RETURN) == PSM_RETURN) ? RETURNsymbol : 
YIELDsymbol;
        if (val->type == st_table) {
                list *l = val->op1->op4.lval;
 
@@ -3346,7 +3346,7 @@ stmt_return(backend *be, stmt *val, int 
                return NULL;
        pushInstruction(mb, q);
        if (q) {
-               stmt *s = stmt_create(be->mvc->sa, st_return);
+               stmt *s = stmt_create(be->mvc->sa, ((flag & PSM_RETURN) == 
PSM_RETURN) ? st_return : st_yield);
 
                s->op1 = val;
                s->flag = nr_declared_tables;
diff --git a/sql/backends/monet5/sql_statement.h 
b/sql/backends/monet5/sql_statement.h
--- a/sql/backends/monet5/sql_statement.h
+++ b/sql/backends/monet5/sql_statement.h
@@ -95,6 +95,7 @@ typedef enum stmt_type {
        st_cond,
        st_control_end,
        st_return,
+       st_yield,
        st_assign
 } st_type;
 
@@ -226,7 +227,7 @@ extern stmt *stmt_affected_rows(backend 
 /* flow control statements */
 extern stmt *stmt_cond(backend *be, stmt *cond, stmt *outer, int loop, int 
anti);
 extern stmt *stmt_control_end(backend *be, stmt *cond);
-extern stmt *stmt_return(backend *be, stmt *val, int nr_of_declared_tables);
+extern stmt *stmt_return(backend *be, stmt *val, int nr_of_declared_tables, 
int flag);
 extern stmt *stmt_assign(backend *be, const char *varname, stmt *val, int 
level);
 
 extern sql_subtype *tail_type(stmt *st);
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -80,6 +80,7 @@ typedef struct expression {
 #define PSM_WHILE 8
 #define PSM_IF 16
 #define PSM_REL 32
+#define PSM_YIELD 64
 
 #define SET_PSM_LEVEL(level)   (level<<8)
 #define GET_PSM_LEVEL(level)   (level>>8)
diff --git a/sql/server/rel_distribute.c b/sql/server/rel_distribute.c
--- a/sql/server/rel_distribute.c
+++ b/sql/server/rel_distribute.c
@@ -104,7 +104,7 @@ exp_replica(mvc *sql, sql_exp *e, char *
                return e;
        if (e->flag & PSM_VAR) 
                return e;
-       if (e->flag & PSM_SET || e->flag & PSM_RETURN) 
+       if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_YIELD)
                e->l = exp_replica(sql, e->l, uri);
        if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
                e->l = exp_replica(sql, e->l, uri);
@@ -229,7 +229,7 @@ exp_distribute(mvc *sql, sql_exp *e)
                return e;
        if (e->flag & PSM_VAR) 
                return e;
-       if (e->flag & PSM_SET || e->flag & PSM_RETURN) 
+       if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_YIELD)
                e->l = exp_distribute(sql, e->l);
        if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
                e->l = exp_distribute(sql, e->l);
@@ -362,7 +362,7 @@ exp_remote_func(mvc *sql, sql_exp *e)
                return e;
        if (e->flag & PSM_VAR) 
                return e;
-       if (e->flag & PSM_SET || e->flag & PSM_RETURN) 
+       if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_YIELD)
                e->l = exp_remote_func(sql, e->l);
        if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
                e->l = exp_remote_func(sql, e->l);
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -81,6 +81,9 @@ exp_print(mvc *sql, stream *fout, sql_ex
                } else if (e->flag & PSM_RETURN) {
                        mnstr_printf(fout, "return ");
                        exp_print(sql, fout, e->l, depth, refs, 0, 0);
+               } else if (e->flag & PSM_YIELD) {
+                       mnstr_printf(fout, "yield ");
+                       exp_print(sql, fout, e->l, depth, refs, 0, 0);
                } else if (e->flag & PSM_WHILE) {
                        mnstr_printf(fout, "while ");
                        exp_print(sql, fout, e->l, depth, refs, 0, 0);
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -541,6 +541,16 @@ exp_return(sql_allocator *sa, sql_exp *v
        return e;
 }
 
+sql_exp *
+exp_yield(sql_allocator *sa, sql_exp *val, int level)
+{
+       sql_exp *e = exp_create(sa, e_psm);
+
+       e->l = val;
+       e->flag = PSM_YIELD + SET_PSM_LEVEL(level);
+       return e;
+}
+
 sql_exp * 
 exp_while(sql_allocator *sa, sql_exp *cond, list *stmts)
 {
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -76,6 +76,7 @@ extern sql_exp * exp_set(sql_allocator *
 extern sql_exp * exp_var(sql_allocator *sa, const char *name, sql_subtype 
*type, int level);
 extern sql_exp * exp_table(sql_allocator *sa, const char *name, sql_table *t, 
int level);
 extern sql_exp * exp_return(sql_allocator *sa, sql_exp *val, int level);
+extern sql_exp * exp_yield(sql_allocator *sa, sql_exp *val, int level);
 extern sql_exp * exp_while(sql_allocator *sa, sql_exp *cond, list *stmts);
 extern sql_exp * exp_if(sql_allocator *sa, sql_exp *cond, list *if_stmts, list 
*else_stmts);
 extern sql_exp * exp_rel(mvc *sql, sql_rel * r);
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -229,7 +229,7 @@ psm_exp_properties(mvc *sql, global_prop
        if (e->type == e_psm) {
                if (e->flag & PSM_SET) {
                        psm_exp_properties(sql, gp, e->l);
-               } else if (e->flag & PSM_RETURN) {
+               } else if (e->flag & PSM_RETURN || e->flag & PSM_YIELD) {
                        psm_exp_properties(sql, gp, e->l);
                } else if (e->flag & PSM_WHILE) {
                        psm_exp_properties(sql, gp, e->l);
@@ -2604,7 +2604,7 @@ exp_case_fixup( mvc *sql, sql_exp *e )
                        /* todo */
                } else if (e->flag & PSM_VAR) {
                        /* todo */
-               } else if (e->flag & PSM_RETURN) {
+               } else if (e->flag & PSM_RETURN || e->flag & PSM_YIELD) {
                        e->l = exp_case_fixup(sql, e->l);
                } else if (e->flag & PSM_WHILE) {
                        e->l = exp_case_fixup(sql, e->l);
@@ -8645,7 +8645,7 @@ rewrite_exp(mvc *sql, sql_exp *e, rewrit
                return e;
        if (e->flag & PSM_VAR) 
                return e;
-       if (e->flag & PSM_SET || e->flag & PSM_RETURN) {
+       if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_YIELD) {
                e->l = rewrite_exp(sql, e->l, rewrite_rel, rewriter, 
has_changes);
        }
        if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
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
@@ -422,16 +422,18 @@ rel_psm_case( mvc *sql, sql_subtype *res
        }
 }
 
-/* return val;
+/* return val; yield val;
  */
 static list * 
-rel_psm_return( mvc *sql, sql_subtype *restype, list *restypelist, symbol 
*return_sym )
+rel_psm_return( mvc *sql, sql_subtype *restype, list *restypelist, symbol 
*return_sym, int token )
 {
        exp_kind ek = {type_value, card_value, FALSE};
-       sql_exp *res;
+       sql_exp *res, *to_append;
        sql_rel *rel = NULL;
        int is_last = 0;
        list *l = sa_list(sql->sa);
+       char* psm_Err = token == SQL_RETURN ? "RETURN" : "YIELD";
+    char* psm_err = token == SQL_RETURN ? "return" : "yield";
 
        if (restypelist)
                ek.card = card_relation;
@@ -440,7 +442,7 @@ rel_psm_return( mvc *sql, sql_subtype *r
                return NULL;
        if (ek.card != card_relation && (!res || !restype ||
                (res = rel_check_type(sql, restype, res, type_equal)) == NULL))
-               return (!restype)?sql_error(sql, 02, "RETURN: return type does 
not match"):NULL;
+               return (!restype)?sql_error(sql, 02, "%s: %s type does not 
match", psm_Err, psm_err):NULL;
        else if (ek.card == card_relation && !rel)
                return NULL;
        
@@ -482,7 +484,7 @@ rel_psm_return( mvc *sql, sql_subtype *r
                const char *tname = t->base.name;
 
                if (cs_size(&t->columns) != list_length(restypelist))
-                       return sql_error(sql, 02, "RETURN: number of columns do 
not match");
+                       return sql_error(sql, 02, "%s: number of columns do not 
match", psm_Err);
                for (n = t->columns.set->h, m = restypelist->h; n && m; n = 
n->next, m = m->next) {
                        sql_column *c = n->data;
                        sql_arg *ce = m->data;
@@ -496,7 +498,9 @@ rel_psm_return( mvc *sql, sql_subtype *r
                rel = rel_project(sql->sa, rel, exps);
                res = exp_rel(sql, rel);
        }
-       append(l, exp_return(sql->sa, res, stack_nr_of_declared_tables(sql)));
+       to_append = (token == SQL_RETURN) ? exp_return(sql->sa, res, 
stack_nr_of_declared_tables(sql)) :
+                        exp_yield(sql->sa, res, 
stack_nr_of_declared_tables(sql));
+       append(l, to_append);
        return l;
 }
 
@@ -557,7 +561,7 @@ static int
 exp_has_return(sql_exp *e) 
 {
        if (e->type == e_psm) {
-               if (e->flag & PSM_RETURN) 
+               if (e->flag & PSM_RETURN)
                        return 1;
                if (e->flag & PSM_IF) 
                        return has_return(e->r) && (!e->f || has_return(e->f));
@@ -572,7 +576,32 @@ has_return( list *l )
        sql_exp *e = n->data;
 
        /* last statment of sequential block */
-       if (exp_has_return(e)) 
+       if (exp_has_return(e))
+               return 1;
+       return 0;
+}
+
+static int has_yield( list *l );
+
+static int
+exp_has_yield(sql_exp *e)
+{
+       if (e->type == e_psm) {
+               if (e->flag & PSM_YIELD)
+                       return 1;
+               if (e->flag & PSM_IF)
+                       return has_yield(e->r) && (!e->f || has_yield(e->f));
+       }
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to