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