Changeset: 07ba4978af36 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/07ba4978af36 Modified Files: sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_cat.c sql/backends/monet5/sql_gencode.c sql/backends/monet5/sql_user.c sql/common/sql_types.c sql/server/rel_psm.c sql/server/sql_env.c sql/server/sql_mvc.c sql/server/sql_mvc.h sql/storage/sql_storage.h sql/storage/store.c Branch: sqlfuncfix Log Message:
Cleanup side_effects flag propagation diffs (truncated from 331 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 @@ -1243,7 +1243,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l stmt *rows = NULL; const char *mod, *fimp; - /* attempt to instantiate nosql functions now, so we can know if we can push candidate lists */ + /* attempt to instantiate MAL functions now, so we can know if we can push candidate lists */ if (f->func->lang == FUNC_LANG_MAL && backend_create_mal_func(be->mvc, f->func) < 0) return NULL; mod = sql_func_mod(f->func); diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c --- a/sql/backends/monet5/sql_cat.c +++ b/sql/backends/monet5/sql_cat.c @@ -1011,8 +1011,29 @@ create_func(mvc *sql, char *sname, char sql->errstr[0] = '\0'; } } + /* set side-effects flag */ + switch(f->lang) { + case FUNC_LANG_R: + case FUNC_LANG_PY: + case FUNC_LANG_PY3: + case FUNC_LANG_MAP_PY: + case FUNC_LANG_MAP_PY3: + case FUNC_LANG_C: + case FUNC_LANG_CPP: + f->side_effect = (list_empty(f->res) || list_empty(f->ops)); /* TODO make this more precise? */ + break; + case FUNC_LANG_MAL: + /* TODO using the 'unsafeProp' from the MAL definition causes many system functions to have a different value */ + f->side_effect = f->type != F_FILT && (list_empty(f->res) || list_empty(f->ops)); + break; + case FUNC_LANG_SQL: + f->side_effect = list_empty(f->res) == 1; + break; + default: + throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s: cannot create new functions using the current language", base, F); + } - switch (mvc_create_func(&nf, sql, NULL, s, f->base.name, f->ops, f->res, f->type, f->lang, f->mod, f->imp, f->query, f->varres, f->vararg, f->system)) { + switch (mvc_create_func(&nf, sql, NULL, s, f->base.name, f->ops, f->res, f->type, f->lang, f->mod, f->imp, f->query, f->varres, f->vararg, f->system, f->side_effect)) { case -1: throw(SQL,"sql.create_func", SQLSTATE(HY013) MAL_MALLOC_FAIL); case -2: @@ -1023,7 +1044,7 @@ create_func(mvc *sql, char *sname, char } switch (nf->lang) { case FUNC_LANG_MAL: - /* instantiate MAL functions while being created */ + /* instantiate MAL functions while being created */ if (backend_create_mal_func(sql, nf) < 0) { if (strlen(sql->errstr) > 6 && sql->errstr[5] == '!') throw(SQL, "sql.create_func", "%s", sql->errstr); 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 @@ -955,12 +955,18 @@ monet5_resolve_function(ptr M, sql_func return 0; /* Some SQL functions MAL mapping such as count(*) aggregate, the number of arguments don't match */ - if (mname == calcRef && fname == getName("=")) + if (mname == calcRef && fname == getName("=")) { + //f->side_effect = 0; return 1; - if (mname == aggrRef && (fname == countRef || fname == count_no_nilRef)) + } + if (mname == aggrRef && (fname == countRef || fname == count_no_nilRef)) { + //f->side_effect = 0; return 1; - if (f->type == F_ANALYTIC) + } + if (f->type == F_ANALYTIC) { + //f->side_effect = 0; return 1; + } c = MCgetClient(clientID); for (m = findModule(c->usermodule, mname); m; m = m->link) { @@ -968,9 +974,10 @@ monet5_resolve_function(ptr M, sql_func InstrPtr sig = getSignature(s); int argc = sig->argc - sig->retc, nfargs = list_length(f->ops), nfres = list_length(f->res); - if ((sig->varargs & VARARGS) == VARARGS || f->vararg || f->varres) + if ((sig->varargs & VARARGS) == VARARGS || f->vararg || f->varres) { + //f->side_effect = (bit) s->def->unsafeProp; return 1; - else if (nfargs == argc && (nfres == sig->retc || (sig->retc == 1 && (IS_FILT(f) || IS_PROC(f))))) { + } else if (nfargs == argc && (nfres == sig->retc || (sig->retc == 1 && (IS_FILT(f) || IS_PROC(f))))) { /* I removed this code because, it was triggering many errors on te SQL <-> MAL translation */ /* Check for types of inputs and outputs. SQL procedures and filter functions always return 1 value in the MAL implementation bool all_match = true; @@ -1004,7 +1011,8 @@ monet5_resolve_function(ptr M, sql_func } } if (all_match)*/ - return 1; + //f->side_effect = (bit) s->def->unsafeProp; + return 1; } } } diff --git a/sql/backends/monet5/sql_user.c b/sql/backends/monet5/sql_user.c --- a/sql/backends/monet5/sql_user.c +++ b/sql/backends/monet5/sql_user.c @@ -297,7 +297,7 @@ monet5_create_privileges(ptr _mvc, sql_s ops = sa_list(m->sa); /* following funcion returns a table (single column) of user names with the approriate scenario (sql) */ - mvc_create_func(&f, m, NULL, s, "db_users", ops, res, F_UNION, FUNC_LANG_MAL, "sql", NULL, "CREATE FUNCTION db_users () RETURNS TABLE( name varchar(2048)) EXTERNAL NAME sql.db_users;", FALSE, FALSE, TRUE); + mvc_create_func(&f, m, NULL, s, "db_users", ops, res, F_UNION, FUNC_LANG_MAL, "sql", NULL, "CREATE FUNCTION db_users () RETURNS TABLE( name varchar(2048)) EXTERNAL NAME sql.db_users;", FALSE, FALSE, TRUE, FALSE); t = mvc_init_create_view(m, s, "users", "create view sys.users as select u.\"name\" as \"name\", " diff --git a/sql/common/sql_types.c b/sql/common/sql_types.c --- a/sql/common/sql_types.c +++ b/sql/common/sql_types.c @@ -654,7 +654,6 @@ sql_create_func_(sql_allocator *sa, cons t->instantiated = TRUE; t->lang = FUNC_LANG_INT; t->semantics = semantics; - t->side_effect = side_effect; t->fix_scale = fix_scale; t->s = NULL; t->system = TRUE; @@ -662,6 +661,7 @@ sql_create_func_(sql_allocator *sa, cons /* grouping aggregate doesn't have a backend */ assert(strlen(imp) == 0 || strlen(mod) == 0 || backend_resolve_function(&(int){0}, t)); + t->side_effect = side_effect; /* backend_resolve_function may set 'side_effect' flag in the future */ return t; } 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 @@ -944,7 +944,7 @@ rel_create_func(sql_query *query, dlist sql->params = NULL; if (create) { - switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, mod, imp, lang_body, (type == F_LOADER)?TRUE:FALSE, vararg, FALSE)) { + switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, mod, imp, lang_body, (type == F_LOADER)?TRUE:FALSE, vararg, FALSE, FALSE)) { case -1: return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL); case -2: @@ -963,7 +963,7 @@ rel_create_func(sql_query *query, dlist if (create) { /* needed for recursive functions */ q = query_cleaned(sql->ta, q); - switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, sql_shared_module_name, NULL, q, FALSE, vararg, FALSE)) { + switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, sql_shared_module_name, NULL, q, FALSE, vararg, FALSE, FALSE)) { case -1: return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL); case -2: @@ -1001,7 +1001,7 @@ rel_create_func(sql_query *query, dlist sql->params = NULL; if (create) { q = query_cleaned(sql->ta, q); - switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, fmod, NULL, q, FALSE, vararg, FALSE)) { + switch (mvc_create_func(&f, sql, sql->sa, s, fname, l, restype, type, lang, fmod, NULL, q, FALSE, vararg, FALSE, FALSE)) { case -1: return sql_error(sql, 01, SQLSTATE(HY013) MAL_MALLOC_FAIL); case -2: diff --git a/sql/server/sql_env.c b/sql/server/sql_env.c --- a/sql/server/sql_env.c +++ b/sql/server/sql_env.c @@ -88,7 +88,7 @@ sql_create_env(mvc *m, sql_schema *s) /* add function */ ops = sa_list(m->sa); - mvc_create_func(&f, m, NULL, s, "env", ops, res, F_UNION, FUNC_LANG_MAL, "inspect", NULL, "CREATE FUNCTION env() RETURNS TABLE( name varchar(1024), value varchar(2048)) EXTERNAL NAME inspect.\"getEnvironment\";", FALSE, FALSE, TRUE); + mvc_create_func(&f, m, NULL, s, "env", ops, res, F_UNION, FUNC_LANG_MAL, "inspect", NULL, "CREATE FUNCTION env() RETURNS TABLE( name varchar(1024), value varchar(2048)) EXTERNAL NAME inspect.\"getEnvironment\";", FALSE, FALSE, TRUE, FALSE); res = sa_list(m->sa); list_append(res, sql_create_arg(m->sa, "schema", sql_bind_localtype("str"), ARG_OUT)); @@ -98,6 +98,6 @@ sql_create_env(mvc *m, sql_schema *s) /* add function */ ops = sa_list(m->sa); - mvc_create_func(&f, m, NULL, s, "var", ops, res, F_UNION, FUNC_LANG_MAL, "sql", NULL, "create function \"sys\".\"var\"() returns table(\"schema\" string, \"name\" string, \"type\" string, \"value\" string) external name \"sql\".\"sql_variables\";", FALSE, FALSE, TRUE); + mvc_create_func(&f, m, NULL, s, "var", ops, res, F_UNION, FUNC_LANG_MAL, "sql", NULL, "create function \"sys\".\"var\"() returns table(\"schema\" string, \"name\" string, \"type\" string, \"value\" string) external name \"sql\".\"sql_variables\";", FALSE, FALSE, TRUE, FALSE); return 0; } diff --git a/sql/server/sql_mvc.c b/sql/server/sql_mvc.c --- a/sql/server/sql_mvc.c +++ b/sql/server/sql_mvc.c @@ -1037,16 +1037,17 @@ mvc_drop_type(mvc *m, sql_schema *s, sql } int -mvc_create_func(sql_func **f, mvc *m, sql_allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system) +mvc_create_func(sql_func **f, mvc *m, sql_allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang, + const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect) { int lres = LOG_OK; TRC_DEBUG(SQL_TRANS, "Create function: %s\n", name); if (sa) { - *f = create_sql_func(m->store, sa, name, args, res, type, lang, mod, impl, query, varres, vararg, system); + *f = create_sql_func(m->store, sa, name, args, res, type, lang, mod, impl, query, varres, vararg, system, side_effect); (*f)->s = s; } else - lres = sql_trans_create_func(f, m->session->tr, s, name, args, res, type, lang, mod, impl, query, varres, vararg, system); + lres = sql_trans_create_func(f, m->session->tr, s, name, args, res, type, lang, mod, impl, query, varres, vararg, system, side_effect); return lres; } diff --git a/sql/server/sql_mvc.h b/sql/server/sql_mvc.h --- a/sql/server/sql_mvc.h +++ b/sql/server/sql_mvc.h @@ -194,7 +194,8 @@ extern sql_trigger *mvc_bind_trigger(mvc extern int mvc_create_type(mvc *sql, sql_schema *s, const char *sqlname, unsigned int digits, unsigned int scale, int radix, const char *impl); extern int mvc_drop_type(mvc *sql, sql_schema *s, sql_type *t, int drop_action); -extern int mvc_create_func(sql_func **f, mvc *m, sql_allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system); +extern int mvc_create_func(sql_func **f, mvc *m, sql_allocator *sa, sql_schema *s, const char *name, list *args, list *res, sql_ftype type, sql_flang lang, + const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect); extern int mvc_drop_func(mvc *c, sql_schema *s, sql_func * func, int drop_action); extern int mvc_drop_all_func(mvc *c, sql_schema *s, list *list_func, int drop_action); diff --git a/sql/storage/sql_storage.h b/sql/storage/sql_storage.h --- a/sql/storage/sql_storage.h +++ b/sql/storage/sql_storage.h @@ -346,7 +346,8 @@ extern int sql_trans_commit(sql_trans *t extern int sql_trans_create_type(sql_trans *tr, sql_schema *s, const char *sqlname, unsigned int digits, unsigned int scale, int radix, const char *impl); extern int sql_trans_drop_type(sql_trans *tr, sql_schema * s, sqlid id, int drop_action); -extern int sql_trans_create_func(sql_func **fres, sql_trans *tr, sql_schema *s, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system); +extern int sql_trans_create_func(sql_func **fres, sql_trans *tr, sql_schema *s, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, + const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect); extern int sql_trans_drop_func(sql_trans *tr, sql_schema *s, sqlid id, int drop_action); extern int sql_trans_drop_all_func(sql_trans *tr, sql_schema *s, list *list_func, int drop_action); @@ -437,7 +438,8 @@ extern sql_key * key_create_done(struct extern sql_idx *create_sql_idx(struct sqlstore *store, sql_allocator *sa, sql_table *t, const char *nme, idx_type it); extern sql_idx *create_sql_ic(struct sqlstore *store, sql_allocator *sa, sql_idx *i, sql_column *c); extern sql_idx *create_sql_idx_done(sql_idx *i); -extern sql_func *create_sql_func(struct sqlstore *store, sql_allocator *sa, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod, const char *impl, const char *query, bit varres, bit vararg, bit system); +extern sql_func *create_sql_func(struct sqlstore *store, sql_allocator *sa, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod, + const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect); /* for alter we need to duplicate a table */ extern sql_table *dup_sql_table(sql_allocator *sa, sql_table *t); diff --git a/sql/storage/store.c b/sql/storage/store.c --- a/sql/storage/store.c +++ b/sql/storage/store.c @@ -939,8 +939,6 @@ load_func(sql_trans *tr, sql_schema *s, t->instantiated = t->lang != FUNC_LANG_SQL && t->lang != FUNC_LANG_MAL; t->type = (sql_ftype) store->table_api.column_find_int(tr, find_sql_column(funcs, "type"), rid); t->side_effect = (bit) store->table_api.column_find_bte(tr, find_sql_column(funcs, "side_effect"), rid); - if (t->type==F_FILT) - t->side_effect=FALSE; t->varres = (bit) store->table_api.column_find_bte(tr, find_sql_column(funcs, "varres"), rid); t->vararg = (bit) store->table_api.column_find_bte(tr, find_sql_column(funcs, "vararg"), rid); t->system = (bit) store->table_api.column_find_bte(tr, find_sql_column(funcs, "system"), rid); @@ -990,9 +988,6 @@ load_func(sql_trans *tr, sql_schema *s, } } } - if (t->type == F_FUNC && !t->res) - t->type = F_PROC; - t->side_effect = (t->type==F_FILT || (t->res && (t->lang==FUNC_LANG_SQL || !list_empty(t->ops))))?FALSE:TRUE; return t; } @@ -1468,11 +1463,10 @@ insert_functions(sql_trans *tr, sql_tabl sqlstore *store = tr->store; for (node *n = funcs_list->h; n; n = n->next) { sql_func *f = n->data; - bit se = (f->type == F_AGGR) ? FALSE : f->side_effect; int number = 0, ftype = (int) f->type, flang = (int) FUNC_LANG_INT; sqlid next_schema = f->s ? f->s->base.id : 0; - if ((res = store->table_api.table_insert(tr, sysfunc, &f->base.id, &f->base.name, &f->imp, &f->mod, &flang, &ftype, &se, &f->varres, &f->vararg, &next_schema, &f->system, &f->semantics))) + if ((res = store->table_api.table_insert(tr, sysfunc, &f->base.id, &f->base.name, &f->imp, &f->mod, &flang, &ftype, &f->side_effect, &f->varres, &f->vararg, &next_schema, &f->system, &f->semantics))) return res; if (f->res && (res = insert_args(tr, sysarg, f->res, f->base.id, "res_%d", &number))) return res; @@ -4815,7 +4809,7 @@ sql_trans_drop_type(sql_trans *tr, sql_s sql_func * create_sql_func(sqlstore *store, sql_allocator *sa, const char *func, list *args, list *res, sql_ftype type, sql_flang lang, const char *mod, - const char *impl, const char *query, bit varres, bit vararg, bit system) + const char *impl, const char *query, bit varres, bit vararg, bit system, bit side_effect) { sql_func *t = SA_ZNEW(sa, sql_func); @@ -4827,7 +4821,7 @@ create_sql_func(sqlstore *store, sql_all t->lang = lang; t->instantiated = lang != FUNC_LANG_SQL && lang != FUNC_LANG_MAL; t->semantics = TRUE; - t->side_effect = (type==F_FILT || (res && (lang==FUNC_LANG_SQL || !list_empty(args))))?FALSE:TRUE; + t->side_effect = side_effect; t->varres = varres; t->vararg = vararg; t->ops = args; @@ -4841,14 +4835,13 @@ create_sql_func(sqlstore *store, sql_all int _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list