Changeset: 43d11329527e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=43d11329527e
Modified Files:
sql/backends/monet5/rel_bin.c
sql/common/sql_types.c
sql/server/rel_select.c
Branch: default
Log Message:
handle case x when y then .. at the rel_bin layer, ie don't add x=y expressions
in rel_select
diffs (239 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
@@ -636,6 +636,7 @@ exp2bin_case(backend *be, sql_exp *fe, s
}
list *exps = fe->l;
+
/*
* left - isel: calls down need id's from the range of left
* res - rsel: updates too res need id's in the range from res
@@ -750,6 +751,166 @@ exp2bin_case(backend *be, sql_exp *fe, s
return res;
}
+static stmt *
+exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt
*isel, int depth)
+{
+ stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = 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, "sys", "not", bt, NULL,
F_FUNC);
+ sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC);
+ sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC);
+ sql_subfunc *cmp;
+
+ 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;
+ node *en = exps->h;
+ sql_exp *e = en->data;
+
+ stmt *nsel = !single_value?isel:NULL;
+ stmt *case_when = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel,
depth+1, 0, 1);
+ if (!case_when)
+ return NULL;
+ cmp = sql_bind_func(be->mvc, "sys", "=", exp_subtype(e),
exp_subtype(e), F_FUNC);
+ if (!cmp)
+ return NULL;
+ if (!single_value && !case_when->nrcols) {
+ stmt *l = isel;
+ if (!l)
+ l = bin_first_column(be, left);
+ case_when = stmt_const(be, l, case_when);
+ case_when->cand = isel;
+ }
+
+ /*
+ * left - isel: calls down need id's from the range of left
+ * res - rsel: updates too res need id's in the range from res
+ */
+ for (en = en->next; en; en = en->next) {
+ sql_exp *e = en->data;
+
+ next_cond = next_cond && en->next; /* last else is only a value
*/
+
+ stmt *nsel = rsel;
+ if (!single_value) {
+ if (/*!next_cond &&*/ rsel && isel) {
+ /* back into left range */
+ nsel = stmt_project(be, rsel, isel);
+ } else if (isel && !rsel)
+ nsel = isel;
+ }
+ stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel,
depth+1, 0, 1);
+
+ if (!es)
+ return NULL;
+ if (next_cond) {
+ stmt *l = case_when;
+ assert(!es->cand || !l->cand || es->cand == l->cand);
+ if (es->cand && !l->cand)
+ l = stmt_project(be, es->cand, case_when);
+ else if (l->cand && !es->cand)
+ es = stmt_project(be, l->cand, es);
+ es = stmt_binop(be, l, es, NULL, cmp);
+ }
+ if (!single_value) {
+ /* create result */
+ if (!res) {
+ stmt *l = isel;
+ if (!l)
+ l = bin_first_column(be, left);
+ res = stmt_const(be, l, stmt_atom(be,
atom_general(be->mvc->sa, exp_subtype(fe), NULL)));
+ ires = l;
+ if (res)
+ res->cand = isel;
+ } else if (res && !next_cond) { /* use result too
update column */
+ stmt *val = es;
+ stmt *pos = rsel;
+
+ if (val->nrcols == 0)
+ val = stmt_const(be, pos, val);
+ else if (!val->cand && nsel)
+ val = stmt_project(be, nsel, val);
+ res = stmt_replace(be, res, pos, val);
+
+ assert(cond);
+
+ if (en->next) {
+ /* osel - rsel */
+ if (!osel)
+ osel = stmt_mirror(be, ires);
+ stmt *d = stmt_tdiff(be, osel, rsel,
NULL);
+ osel = rsel = stmt_project(be, d, osel);
+ }
+ }
+ if (next_cond) {
+ ncond = cond = es;
+ if (!ncond->nrcols) {
+ if (osel) {
+ ncond = stmt_const(be, nsel,
ncond);
+ ncond->cand = nsel;
+ } else if (isel) {
+ ncond = stmt_const(be, isel,
ncond);
+ ncond->cand = isel;
+ } else
+ ncond = stmt_const(be,
bin_first_column(be, left), ncond);
+ }
+ if (isel && !ncond->cand)
+ ncond = stmt_project(be, nsel, ncond);
+ stmt *s = stmt_uselect(be, ncond, stmt_bool(be,
1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
+ if (rsel && ncond->cand)
+ rsel = stmt_project(be, s, rsel);
+ else
+ rsel = s;
+ }
+ } else {
+ if (!res) {
+ /* if_barrier ... */
+ assert(next_cond);
+ if (next_cond) {
+ if (cond) {
+ ncond = stmt_binop(be, cond,
es, nsel, 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, nsel, not);
+
+ sql_subfunc *isnull =
sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC);
+ cond = stmt_binop(be, cond,
stmt_unop(be, cond, nsel, isnull), nsel, or);
+ if (ocond)
+ cond = stmt_binop(be, ocond,
cond, nsel, 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)
{
@@ -1027,6 +1188,8 @@ exp_bin(backend *be, sql_exp *e, stmt *l
if (strcmp(sql_func_mod(f->func), "calc") == 0 &&
strcmp(sql_func_imp(f->func), "ifthenelse") == 0)
return exp2bin_case(be, e, left, right, sel,
depth);
+ if (strcmp(sql_func_mod(f->func), "") == 0 &&
strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name,
"casewhen") == 0)
+ return exp2bin_casewhen(be, e, left, right,
sel, depth);
if (strcmp(sql_func_mod(f->func), "") == 0 &&
strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name,
"coalesce") == 0)
return exp2bin_coalesce(be, e, left, right,
sel, depth);
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
@@ -950,9 +950,10 @@ sqltypeinit( sql_allocator *sa)
sql_create_func(sa, "least", "calc", "min_no_nil", TRUE, FALSE,
SCALE_FIX, 0, ANY, 2, ANY, ANY);
sql_create_func(sa, "greatest", "calc", "max_no_nil", TRUE, FALSE,
SCALE_FIX, 0, ANY, 2, ANY, ANY);
sql_create_func(sa, "ifthenelse", "calc", "ifthenelse", TRUE, FALSE,
SCALE_FIX, 0, ANY, 3, BIT, ANY, ANY);
- /* nullif and coalesce don't have a backend implementation */
+ /* nullif, coalesce and casewhen don't have a backend implementation */
sql_create_func(sa, "nullif", "", "", TRUE, FALSE, SCALE_FIX, 0, ANY,
2, ANY, ANY);
sql_create_func(sa, "coalesce", "", "", TRUE, FALSE, SCALE_FIX, 0, ANY,
2, ANY, ANY);
+ sql_create_func(sa, "casewhen", "", "", TRUE, FALSE, SCALE_FIX, 0, ANY,
2, ANY, ANY);
/* needed for count(*) and window functions without input col */
sql_create_func(sa, "star", "", "", TRUE, FALSE, SCALE_FIX, 0, ANY, 0);
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -3819,6 +3819,8 @@ rel_case(sql_query *query, sql_rel **rel
return NULL;
sql_find_subtype(&bt, "boolean", 0, 0);
list *args = sa_list(sql->sa);
+ if (opt_cond_exp)
+ append(args, opt_cond_exp);
for (node *n = conds->h, *m = results->h; n && m; n = n->next, m =
m->next) {
sql_exp *cond = n->data;
sql_exp *result = m->data;
@@ -3828,9 +3830,7 @@ rel_case(sql_query *query, sql_rel **rel
if (!(cond = exp_check_type(sql, condtype, rel ? *rel : NULL,
cond, type_equal)))
return NULL;
- if (opt_cond_exp && !(cond = rel_binop_(sql, rel ? *rel : NULL,
n == conds->h ? opt_cond_exp : exp_copy(sql, opt_cond_exp), cond, "sys", "=",
card_value)))
- return NULL;
- if (!(cond = exp_check_type(sql, &bt, rel ? *rel : NULL, cond,
type_equal)))
+ if (!opt_cond_exp && !(cond = exp_check_type(sql, &bt, rel ?
*rel : NULL, cond, type_equal)))
return NULL;
append(args, cond);
append(args, result);
@@ -3838,8 +3838,11 @@ rel_case(sql_query *query, sql_rel **rel
assert(res);
if (res)
list_append(args, res);
- list *types = append(append(append(sa_list(sql->sa), condtype),
restype), restype);
- sql_subfunc *ifthenelse = find_func(sql, NULL, "ifthenelse",
list_length(types), F_FUNC, NULL);
+ list *types = sa_list(sql->sa);
+ if (!opt_cond_exp)
+ types = append(sa_list(sql->sa), condtype);
+ types = append(append(types, restype), restype);
+ sql_subfunc *ifthenelse = find_func(sql, NULL,
opt_cond_exp?"casewhen":"ifthenelse", list_length(types), F_FUNC, NULL);
res = exp_op(sql->sa, args, ifthenelse);
((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(sql->sa,
restype->type, restype->digits, restype->scale);
return res;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list