Changeset: f900af1e70a0 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=f900af1e70a0 Added Files: sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.sql sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.err sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.out Modified Files: sql/server/rel_dump.c sql/server/rel_optimizer.c sql/server/rel_psm.c Branch: Oct2014 Log Message:
handle psm expressions in exp_print and exp_case_fixup (solving the div_by_zero bug 3555) diffs (238 lines): 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 @@ -26,6 +26,7 @@ #include "rel_prop.h" #include "rel_select.h" #include "rel_semantic.h" +#include "rel_psm.h" static void print_indent(mvc *sql, stream *fout, int depth) @@ -80,6 +81,28 @@ exp_print(mvc *sql, stream *fout, sql_ex if (!e) return; switch(e->type) { + case e_psm: { + if (e->flag & PSM_SET) { + /* todo */ + } else if (e->flag & PSM_VAR) { + /* todo */ + } else if (e->flag & PSM_RETURN) { + mnstr_printf(fout, "return "); + exp_print(sql, fout, e->l, depth, 0, 0); + } else if (e->flag & PSM_WHILE) { + mnstr_printf(fout, "while "); + exp_print(sql, fout, e->l, depth, 0, 0); + exps_print(sql, fout, e->r, depth, alias, 0); + } else if (e->flag & PSM_IF) { + mnstr_printf(fout, "if "); + exp_print(sql, fout, e->l, depth, 0, 0); + exps_print(sql, fout, e->r, depth, alias, 0); + if (e->f) + exps_print(sql, fout, e->f, depth, alias, 0); + } else if (e->flag & PSM_REL) { + } + break; + } case e_convert: { char *to_type = sql_subtype_string(&e->tpe); mnstr_printf(fout, "%s[", to_type); @@ -340,7 +363,7 @@ rel_print_(mvc *sql, stream *fout, sql_ rel_print_(sql, fout, rel->l, depth+1, refs); if (rel->r) rel_print_(sql, fout, rel->r, depth+1, refs); - if (rel->exps) + if (rel->exps && rel->flag == DDL_PSM) exps_print(sql, fout, rel->exps, depth, 1, 0); break; case op_join: 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 @@ -27,6 +27,7 @@ #include "rel_select.h" #include "rel_updates.h" #include "rel_planner.h" +#include "rel_psm.h" #include "sql_env.h" #define new_func_list(sa) sa_list(sa) @@ -2324,6 +2325,25 @@ static sql_exp * exp_case_fixup( mvc *sql, sql_exp *e ) { /* only functions need fix up */ + if (e->type == e_psm) { + if (e->flag & PSM_SET) { + /* todo */ + } else if (e->flag & PSM_VAR) { + /* todo */ + } else if (e->flag & PSM_RETURN) { + e->l = exp_case_fixup(sql, e->l); + } else if (e->flag & PSM_WHILE) { + e->l = exp_case_fixup(sql, e->l); + e->r = exps_case_fixup(sql, e->r, NULL, 0); + } else if (e->flag & PSM_IF) { + e->l = exp_case_fixup(sql, e->l); + e->r = exps_case_fixup(sql, e->r, NULL, 0); + if (e->f) + e->f = exps_case_fixup(sql, e->f, NULL, 0); + } else if (e->flag & PSM_REL) { + } + return e; + } if (e->type == e_func && e->l && !is_rank_op(e) ) { list *l = new_exp_list(sql->sa), *args = e->l; node *n; @@ -2395,7 +2415,7 @@ rel_case_fixup(int *changes, mvc *sql, s { (void)changes; /* only go through it once, ie don't mark for changes */ - if (is_project(rel->op) && rel->exps) { + if ((is_project(rel->op) || (rel->op == op_ddl && rel->flag == DDL_PSM)) && rel->exps) { list *exps = rel->exps; node *n; int needed = 0; @@ -2404,7 +2424,7 @@ rel_case_fixup(int *changes, mvc *sql, s sql_exp *e = n->data; if (e->type == e_func || e->type == e_convert || - e->type == e_aggr) + e->type == e_aggr || e->type == e_psm) needed = 1; } if (!needed) @@ -7038,7 +7058,7 @@ static sql_rel * #endif /* simple merging of projects */ - if (gp.cnt[op_project]) { + if (gp.cnt[op_project] || gp.cnt[op_ddl]) { rel = rewrite(sql, rel, &rel_merge_projects, &changes); if (level <= 0) { rel = rewrite(sql, rel, &rel_case_fixup, &changes); 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 @@ -770,15 +770,15 @@ rel_create_func(mvc *sql, dlist *qname, if (body && lang > FUNC_LANG_SQL) { char *lang_body = body->h->data.sval; char *mod = (lang == FUNC_LANG_R)?"rapi": - (lang == FUNC_LANG_C)?"capi": - (lang == FUNC_LANG_J)?"japi":"unknown"; + (lang == FUNC_LANG_C)?"capi": + (lang == FUNC_LANG_J)?"japi":"unknown"; sql->params = NULL; - if (create) { - f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, mod, fname, lang_body, FALSE, vararg); + if (create) { + f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, mod, fname, lang_body, FALSE, vararg); } else if (!sf) { return sql_error(sql, 01, "CREATE %s%s: R function %s.%s not bound", KF, F, s->base.name, fname ); } else { - sql_func *f = sf->func; + sql_func *f = sf->func; f->mod = _STRDUP("rapi"); f->imp = _STRDUP("eval"); if (res && restype) diff --git a/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.sql b/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.sql new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.sql @@ -0,0 +1,6 @@ +CREATE FUNCTION my_avg(total INT, cnt INT) RETURNS INT +BEGIN + RETURN CASE WHEN cnt <> 0 THEN total / cnt ELSE -1 END; +END; +SELECT my_avg(0, 0); +DROP FUNCTION my_avg; diff --git a/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.err b/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.err new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.err @@ -0,0 +1,37 @@ +stderr of test 'div_by_zero_in_return.Bug-3555` in directory 'sql/test/BugTracker-2014` itself: + + +# 21:13:46 > +# 21:13:46 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "mapi_open=true" "--set" "mapi_port=38269" "--set" "mapi_usock=/var/tmp/mtest-27060/.s.monetdb.38269" "--set" "monet_prompt=" "--forcemito" "--set" "mal_listing=2" "--dbpath=/home/niels/scratch/rc-monetdb/Linux-x86_64/var/MonetDB/mTests_sql_test_BugTracker-2014" "--set" "mal_listing=0" "--set" "embedded_r=yes" +# 21:13:46 > + +# builtin opt gdk_dbpath = /home/niels/scratch/rc-monetdb/Linux-x86_64/var/monetdb5/dbfarm/demo +# builtin opt gdk_debug = 0 +# builtin opt gdk_vmtrim = no +# builtin opt monet_prompt = > +# builtin opt monet_daemon = no +# builtin opt mapi_port = 50000 +# builtin opt mapi_open = false +# builtin opt mapi_autosense = false +# builtin opt sql_optimizer = default_pipe +# builtin opt sql_debug = 0 +# cmdline opt gdk_nr_threads = 0 +# cmdline opt mapi_open = true +# cmdline opt mapi_port = 38269 +# cmdline opt mapi_usock = /var/tmp/mtest-27060/.s.monetdb.38269 +# cmdline opt monet_prompt = +# cmdline opt mal_listing = 2 +# cmdline opt gdk_dbpath = /home/niels/scratch/rc-monetdb/Linux-x86_64/var/MonetDB/mTests_sql_test_BugTracker-2014 +# cmdline opt mal_listing = 0 +# cmdline opt embedded_r = yes +# cmdline opt gdk_debug = 536870922 + +# 21:13:47 > +# 21:13:47 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-27060" "--port=38269" +# 21:13:47 > + + +# 21:13:47 > +# 21:13:47 > "Done." +# 21:13:47 > + diff --git a/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.out b/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.out new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2014/Tests/div_by_zero_in_return.Bug-3555.stable.out @@ -0,0 +1,43 @@ +stdout of test 'div_by_zero_in_return.Bug-3555` in directory 'sql/test/BugTracker-2014` itself: + + +# 21:13:46 > +# 21:13:46 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "mapi_open=true" "--set" "mapi_port=38269" "--set" "mapi_usock=/var/tmp/mtest-27060/.s.monetdb.38269" "--set" "monet_prompt=" "--forcemito" "--set" "mal_listing=2" "--dbpath=/home/niels/scratch/rc-monetdb/Linux-x86_64/var/MonetDB/mTests_sql_test_BugTracker-2014" "--set" "mal_listing=0" "--set" "embedded_r=yes" +# 21:13:46 > + +# MonetDB 5 server v11.19.0 +# This is an unreleased version +# Serving database 'mTests_sql_test_BugTracker-2014', using 4 threads +# Compiled for x86_64-unknown-linux-gnu/64bit with 64bit OIDs dynamically linked +# Found 7.334 GiB available main-memory. +# Copyright (c) 1993-July 2008 CWI. +# Copyright (c) August 2008-2014 MonetDB B.V., all rights reserved +# Visit http://www.monetdb.org/ for further information +# Listening for connection requests on mapi:monetdb://localhost.nes.nl:38269/ +# Listening for UNIX domain connection requests on mapi:monetdb:///var/tmp/mtest-27060/.s.monetdb.38269 +# MonetDB/GIS module loaded +# MonetDB/SQL module loaded +# MonetDB/R module loaded + +Ready. + +# 21:13:47 > +# 21:13:47 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-27060" "--port=38269" +# 21:13:47 > + +#CREATE FUNCTION my_avg(total INT, cnt INT) RETURNS INT +#BEGIN +# RETURN CASE WHEN cnt <> 0 THEN total / cnt ELSE -1 END; +#END; +#SELECT my_avg(0, 0); +% .L # table_name +% my_avg_single_value # name +% int # type +% 2 # length +[ -1 ] +#DROP FUNCTION my_avg; + +# 21:13:47 > +# 21:13:47 > "Done." +# 21:13:47 > + _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list