Changeset: c10635f623c2 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c10635f623c2 Modified Files: sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_statement.c sql/server/rel_select.c sql/server/rel_unnest.c sql/test/BugDay_2005-11-09_2.9.3/Tests/sql_server_crash.SF-1080024.stable.out sql/test/BugTracker-2009/Tests/case_evaluates_all_branches.SF-2893484.stable.out sql/test/BugTracker-2012/Tests/case_evaluated_too_early.Bug-3186.stable.out sql/test/BugTracker-2019/Tests/duplicates-not-eliminated-long-CASE-stmt.Bug-6697.stable.out sql/test/BugTracker-2019/Tests/prepare-types.Bug-6724.stable.out sql/test/BugTracker/Tests/case_with_aggr.SF-1876779.stable.out sql/test/BugTracker/Tests/case_with_aggr.SF-1876779.stable.out.int128 sql/test/SQLancer/Tests/sqlancer03.stable.err sql/test/Tests/coalesce.stable.out sql/test/remote/Tests/partition_elim.stable.out Branch: default Log Message:
implemented case/coalesce as var-arg virtual functions. Re-implemented the handling of those in rel_bin diffs (truncated from 2689 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 @@ -25,7 +25,7 @@ #define OUTER_ZERO 64 -static stmt * exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, stmt *cond, int depth, int reduce); +static stmt * exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, int reduce); static stmt * rel_bin(backend *be, sql_rel *rel); static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs); @@ -288,7 +288,7 @@ distinct_value_list(backend *be, list *v /* create bat append values */ for (node *n = vals->h; n; n = n->next) { sql_exp *e = n->data; - stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0); + stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0); if (exp_is_null(e)) *last_null_value = i; @@ -366,7 +366,7 @@ handle_in_exps(backend *be, sql_exp *ce, { mvc *sql = be->mvc; node *n; - stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, NULL, 0, 0); + stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, 0, 0); if(!c) return NULL; @@ -384,7 +384,7 @@ handle_in_exps(backend *be, sql_exp *ce, for( n = nl->h; n; n = n->next) { sql_exp *e = n->data; - stmt *i = exp_bin(be, use_r?e->r:e, left, right, grp, ext, cnt, NULL, NULL, 0, 0); + stmt *i = exp_bin(be, use_r?e->r:e, left, right, grp, ext, cnt, NULL, 0, 0); if(!i) return NULL; @@ -406,7 +406,7 @@ handle_in_exps(backend *be, sql_exp *ce, s = sel; for( n = nl->h; n; n = n->next) { sql_exp *e = n->data; - stmt *i = exp_bin(be, use_r?e->r:e, left, right, grp, ext, cnt, NULL, NULL, 0, 0); + stmt *i = exp_bin(be, use_r?e->r:e, left, right, grp, ext, cnt, NULL, 0, 0); if(!i) return NULL; @@ -484,7 +484,7 @@ value_list(backend *be, list *vals, stmt l = sa_list(be->mvc->sa); for (node *n = vals->h; n; n = n->next) { sql_exp *e = n->data; - stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, NULL, 0, 0); + stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0); if (!i) return NULL; @@ -505,7 +505,7 @@ exp_list(backend *be, list *exps, stmt * for( n = exps->h; n; n = n->next) { sql_exp *e = n->data; - stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, NULL, 0, 0); + stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, 0, 0); if(!i) return NULL; @@ -552,7 +552,7 @@ exp_bin_or(backend *be, sql_exp *e, stmt /* propagate the anti flag */ if (anti) set_anti(c); - s = exp_bin(be, c, left, right, grp, ext, cnt, sin, NULL, depth, reduce); + s = exp_bin(be, c, left, right, grp, ext, cnt, sin, depth, reduce); if (!s) return s; @@ -579,7 +579,7 @@ exp_bin_or(backend *be, sql_exp *e, stmt /* propagate the anti flag */ if (anti) set_anti(c); - s = exp_bin(be, c, left, right, grp, ext, cnt, sin, NULL, depth, reduce); + s = exp_bin(be, c, left, right, grp, ext, cnt, sin, depth, reduce); if (!s) return s; @@ -620,8 +620,219 @@ exp_bin_or(backend *be, sql_exp *e, stmt return stmt_tunion(be, sel1, sel2); } +static stmt * +exp2bin_case(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth) +{ + stmt *res = NULL, *sel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL; + int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols)); + char name[16], *nme = NULL; + sql_subtype *bt = sql_bind_localtype("bit"); + sql_subfunc *not = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "not", bt, NULL, F_FUNC); + sql_subfunc *or = sql_bind_func(be->mvc->sa, NULL, "or", bt, bt, F_FUNC); + sql_subfunc *and = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "and", bt, bt, F_FUNC); + list *exps = fe->l; + + if (single_value) { + /* var_x = nil; */ + nme = number2name(name, sizeof(name), ++be->mvc->label); + (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2); + } + + for (node *en = exps->h; en; en = en->next) { + sql_exp *e = en->data; + + next_cond = next_cond && en->next; /* last else is only a value */ + + stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, !next_cond?sel:NULL, depth+1, 0); + + if (!es) + return NULL; + if (!single_value) { + /* create result */ + if (!res) { + stmt *l = bin_first_column(be, left); + res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL))); + } else if (res && !next_cond) { /* use result too update column */ + stmt *val = es, *pos = sel; + + if (val->nrcols == 0) + val = stmt_const(be, pos, val); + else if (val->cand != sel) + val = stmt_project(be, sel, val); + res = stmt_replace(be, res, pos, val); + + assert(cond); + + cond = stmt_unop(be, cond, not); + + sql_subfunc *isnull = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "isnull", bt, NULL, F_FUNC); + cond = stmt_binop(be, cond, stmt_unop(be, cond, isnull), or); + if (ocond) + cond = stmt_binop(be, ocond, cond, and); + ocond = cond; + } + if ((next_cond || (en->next && !en->next->next)) && ncond) { /* else if / else */ + if (next_cond) { + ncond = stmt_binop(be, cond, es, and); + cond = es; + } else { + ncond = cond; + } + } else if (next_cond && !ncond) { + ncond = cond = es; + } + if (ncond && (next_cond || (en->next && !en->next->next))) { + if (!ncond->nrcols) + ncond = stmt_const(be, bin_first_column(be, left), ncond); + sel = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, isel, 0/*anti*/, 0); + } + } else { + if (!res) { + /* if_barrier ... */ + assert(next_cond); + if (next_cond) { + if (cond) { + ncond = stmt_binop(be, cond, es, and); + } else { + ncond = es; + } + cond = es; + } + } else { + /* var_x = s */ + (void)stmt_assign(be, NULL, nme, es, 2); + /* endif_barrier */ + (void)stmt_control_end(be, res); + res = NULL; + + if (en->next) { + cond = stmt_unop(be, cond, not); + + sql_subfunc *isnull = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "isnull", bt, NULL, F_FUNC); + cond = stmt_binop(be, cond, stmt_unop(be, cond, isnull), or); + if (ocond) + cond = stmt_binop(be, ocond, cond, and); + ocond = cond; + if (!en->next->next) + ncond = cond; + } + } + if (ncond && (next_cond || (en->next && !en->next->next))) { + /* if_barrier ... */ + res = stmt_cond(be, ncond, NULL, 0, 0); + } + } + next_cond = !next_cond; + } + if (single_value) + return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2); + return res; +} + +static stmt* +exp2bin_coalesce(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth) +{ + stmt *res = NULL, *sel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL; + int single_value = (fe->card <= CARD_ATOM); + char name[16], *nme = NULL; + sql_subtype *bt = sql_bind_localtype("bit"); + sql_subfunc *and = sql_bind_func(be->mvc->sa, NULL, "and", bt, bt, F_FUNC); + sql_subfunc *not = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "not", bt, NULL, F_FUNC); + + if (single_value) { + /* var_x = nil; */ + nme = number2name(name, sizeof(name), ++be->mvc->label); + (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2); + } + + list *exps = fe->l; + osel = sel = isel; + for (node *en = exps->h; en; en = en->next) { + sql_exp *e = en->data; + stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, sel, depth+1, 0); + + if (!es) + return NULL; + /* create result */ + if (!single_value) { + if (!res) { + stmt *l = bin_first_column(be, left); + res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL))); + } + if (res) { + if (sel && es->cand != sel) { + assert(es->cand == NULL); + es = stmt_project(be, sel, es); + es->cand = sel; + } + stmt *val = es; + stmt *pos = sel; + + if (en->next) { + sql_subfunc *a = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "isnotnull", tail_type(es), NULL, F_FUNC); + ncond = stmt_unop(be, es, a); + if (ncond->nrcols == 0) { + stmt *l = bin_first_column(be, left); + if (sel && l) + l = stmt_project(be, sel, l); + ncond = stmt_const(be, l, ncond); + if (sel) + ncond->cand = sel; + } + stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 0/*anti*/, 0); + val = stmt_project(be, s, es); + if (pos && ncond->cand == sel) + pos = sel = stmt_project(be, s, pos); + else + pos = sel = s; + val->cand = pos; + } + if (val->nrcols == 0) + val = stmt_const(be, pos, val); + else if (val->cand != sel) + val = stmt_project(be, sel, val); + res = stmt_replace(be, res, pos, val); + } + if (en->next) { /* handled then part */ + stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 1/*anti*/, 0); + if (osel && ncond->cand == osel) + osel = sel = stmt_project(be, s, osel); + else + osel = sel = s; + } + } else { + stmt *cond = ocond; + if (en->next) { + sql_subfunc *a = sql_bind_func(be->mvc->sa, be->mvc->session->schema, "isnotnull", tail_type(es), NULL, F_FUNC); + ncond = stmt_unop(be, es, a); + + if (ocond) + cond = stmt_binop(be, ocond, ncond, and); + else + cond = ncond; + } + + /* if_barrier ... */ + stmt *b = stmt_cond(be, cond, NULL, 0, 0); + /* var_x = s */ + (void)stmt_assign(be, NULL, nme, es, 2); + /* endif_barrier */ + (void)stmt_control_end(be, b); + + cond = stmt_unop(be, ncond, not); + if (ocond) + ocond = stmt_binop(be, cond, ocond, and); + else + ocond = cond; + } + } + if (single_value) + return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2); + return res; +} + stmt * _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list