Changeset: b1a3906fd3b0 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b1a3906fd3b0
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/common/sql_types.c
        sql/include/sql_catalog.h
Branch: unlock
Log Message:

merged with default


diffs (truncated from 630 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
@@ -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
@@ -87,6 +87,37 @@ unsigned int bits2digits(unsigned int bi
 #endif
 }
 
+unsigned int type_digits_to_char_digits(sql_subtype *t)
+{
+       if (!t)
+               return 0;
+       switch (t->type->eclass) {
+               case EC_BIT:
+                       return 1;
+               case EC_POS:
+               case EC_NUM:
+               case EC_MONTH:
+                       return bits2digits(t->digits) + 1; /* add '-' */
+               case EC_FLT:
+                       return bits2digits(t->digits) + 2; /* TODO for 
floating-points maybe more is needed */
+               case EC_DEC:
+               case EC_SEC:
+                       return t->digits + 2; /* add '-' and '.' */
+               case EC_TIMESTAMP:
+               case EC_TIMESTAMP_TZ:
+                       return 40; /* TODO this needs more tunning */
+               case EC_TIME:
+               case EC_TIME_TZ:
+                       return 20; /* TODO this needs more tunning */
+               case EC_DATE:
+                       return 20; /* TODO this needs more tunning */
+               case EC_BLOB:
+                       return t->digits * 2; /* TODO BLOBs don't have digits, 
so this is wrong */
+               default:
+                       return t->digits; /* What to do with EC_GEOM? */
+       }
+}
+
 /* 0 cannot convert */
 /* 1 set operations have very limited coersion rules */
 /* 2 automatic coersion (could still require dynamic checks for overflow) */
@@ -919,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/common/sql_types.h b/sql/common/sql_types.h
--- a/sql/common/sql_types.h
+++ b/sql/common/sql_types.h
@@ -23,6 +23,7 @@ extern list *funcs;
 
 extern unsigned int bits2digits(unsigned int b);
 extern unsigned int digits2bits(unsigned int d);
+extern unsigned int type_digits_to_char_digits(sql_subtype *t);
 
 extern int sql_type_convert(int form, int to); /* return 1, convert possible 
but it's a down cast, 2 convert possible can be done savely */
 extern bool is_commutative(const char *fnm);   /* return true if commutative */
diff --git a/sql/include/sql_catalog.h b/sql/include/sql_catalog.h
--- a/sql/include/sql_catalog.h
+++ b/sql/include/sql_catalog.h
@@ -85,7 +85,6 @@ typedef enum sql_dependency {
 #define DIGITS_ADD     5       /* some types grow under functions (concat) */
 #define INOUT          6       /* output type equals input type */
 #define SCALE_EQ       7       /* user defined functions need equal scales */
-#define SCALE_DIGITS_FIX 8     /* the geom module requires the types and 
functions to have the same scale and digits */
 
 /* Warning TR flags is a bitmask */
 #define TR_NEW 1
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
@@ -449,7 +449,8 @@ static list *
 check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, 
sql_subfunc *sf, int maybe_zero_or_one)
 {
        list *nexps = new_exp_list(sql->sa);
-       sql_subtype *atp = NULL, super;
+       sql_subtype *atp = NULL, super, *res = !list_empty(sf->res) ? 
sf->res->h->data: NULL;
+       unsigned int rdigits = 0; /* used for res of type char and varchar */
 
        /* find largest any type argument */
        for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = 
m->next) {
@@ -471,10 +472,12 @@ check_arguments_and_find_largest_any_typ
        for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = 
m->next) {
                sql_arg *a = m->data;
                sql_exp *e = n->data;
-               sql_subtype *ntp = &a->type;
+               sql_subtype *ntp = &a->type, *t = exp_subtype(e);
 
                if (a->type.type->eclass == EC_ANY && atp)
                        ntp = sql_create_subtype(sql->sa, atp->type, 
atp->digits, atp->scale);
+               else if (t && ntp->digits == 0 && 
(!strcmp(a->type.type->sqlname, "char") || !strcmp(a->type.type->sqlname, 
"varchar")))
+                       ntp = sql_create_subtype(sql->sa, a->type.type, 
type_digits_to_char_digits(t), 0);
                if (!(e = exp_check_type(sql, ntp, rel, e, type_equal)))
                        return NULL;
                if (maybe_zero_or_one && e->card > CARD_ATOM) {
@@ -482,10 +485,28 @@ check_arguments_and_find_largest_any_typ
                        e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, 
has_nil(e));
                }
                append(nexps, e);
+
+               /* for (var)char returning functions the output type will be 
the biggest string found except for fix_scale cases */
+               if (res && res->digits == 0 && (t = exp_subtype(e)) && 
(!strcmp(res->type->sqlname, "char") || !strcmp(res->type->sqlname, 
"varchar"))) {
+                       unsigned int tdigits = type_digits_to_char_digits(t);
+                       if (sf->func->fix_scale == DIGITS_ADD) {
+                               rdigits += tdigits;
+                               if (rdigits >= (unsigned int) INT_MAX)
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to