Changeset: 96373e9a31ff for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/96373e9a31ff Modified Files: sql/backends/monet5/sql_upgrades.c sql/server/rel_optimizer.c Branch: properties Log Message:
Merged with default diffs (truncated from 538 to 300 lines): diff --git a/gdk/ChangeLog b/gdk/ChangeLog --- a/gdk/ChangeLog +++ b/gdk/ChangeLog @@ -1,3 +1,8 @@ # ChangeLog file for GDK # This file is updated with Maddlog +* Tue Jan 25 2022 Sjoerd Mullender <[email protected]> +- When adding or subtracting months from a date or timestamp value, + clamp the result to the calculated month instead of wrapping to the + beginning of the next month. See bug 7227. + diff --git a/gdk/gdk_time.c b/gdk/gdk_time.c --- a/gdk/gdk_time.c +++ b/gdk/gdk_time.c @@ -172,12 +172,7 @@ date_add_month(date dt, int months) m = (m - 1) % 12 + 1; } if (d > monthdays(y, m)) { - d -= monthdays(y, m); - if (++m > 12) { - m = 1; - if (++y > YEAR_MAX) - return date_nil; - } + d = monthdays(y, m); } return mkdate(y, m, d); } diff --git a/sql/backends/monet5/dict.c b/sql/backends/monet5/dict.c --- a/sql/backends/monet5/dict.c +++ b/sql/backends/monet5/dict.c @@ -720,7 +720,7 @@ DICTthetaselect(Client cntxt, MalBlkPtr } else assert(0); } else { - bn = BATdense(0, 0, 0); + bn = BATdense(0, 0, op[0] == '!' ? BATcount(lv) : 0); /* for '!' if it didn't find, then all are different */ } } else { /* select + intersect */ if (ATOMextern(lv->ttype)) diff --git a/sql/backends/monet5/sql_upgrades.c b/sql/backends/monet5/sql_upgrades.c --- a/sql/backends/monet5/sql_upgrades.c +++ b/sql/backends/monet5/sql_upgrades.c @@ -674,12 +674,12 @@ sql_update_nov2019_missing_dependencies( ppos = pos; /* later check if found updatable database objects */ os_iterator(&si, sql->session->tr->cat->schemas, sql->session->tr, NULL); - for (sql_base *b = oi_next(&si); b; oi_next(&si)) { + for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) { sql_schema *s = (sql_schema*)b; struct os_iter oi; os_iterator(&oi, s->funcs, sql->session->tr, NULL); - for (sql_base *b = oi_next(&oi); b; oi_next(&oi)) { + for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) { sql_func *f = (sql_func*)b; if (f->query && f->lang == FUNC_LANG_SQL) { 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 @@ -7473,6 +7473,57 @@ rel_select_order(visitor *v, sql_rel *re return rel; } +/* + * Casting decimal values on both sides of a compare expression is expensive, + * both in preformance (cpu cost) and memory requirements (need for large + * types). + */ + +#define reduce_scale_tpe(tpe, uval) \ + do { \ + tpe v = uval; \ + if (v != 0) { \ + while( (v/10)*10 == v ) { \ + i++; \ + v /= 10; \ + } \ + nval = v; \ + } \ + } while (0) + +static atom * +reduce_scale(mvc *sql, atom *a) +{ + int i = 0; + atom *na = a; +#ifdef HAVE_HGE + hge nval = 0; +#else + lng nval = 0; +#endif + +#ifdef HAVE_HGE + if (a->data.vtype == TYPE_hge) { + reduce_scale_tpe(hge, a->data.val.hval); + } else +#endif + if (a->data.vtype == TYPE_lng) { + reduce_scale_tpe(lng, a->data.val.lval); + } else if (a->data.vtype == TYPE_int) { + reduce_scale_tpe(int, a->data.val.ival); + } else if (a->data.vtype == TYPE_sht) { + reduce_scale_tpe(sht, a->data.val.shval); + } else if (a->data.vtype == TYPE_bte) { + reduce_scale_tpe(bte, a->data.val.btval); + } + if (i) { + na = atom_int(sql->sa, &a->tpe, nval); + if (na->tpe.scale) + na->tpe.scale -= i; + } + return na; +} + static inline sql_exp * rel_simplify_predicates(visitor *v, sql_rel *rel, sql_exp *e) { @@ -7550,9 +7601,67 @@ rel_simplify_predicates(visitor *v, sql_ list *r = e->r; e = exp_compare(v->sql->sa, l->h->data, r->h->data, is_anti(e) ? cmp_notequal : cmp_equal); v->changes++; - return e; - } - return e; + } + } + /* rewrite e if left or right is a cast */ + if (is_compare(e->type) && !e->f && is_theta_exp(e->flag) && (((sql_exp*)e->l)->type == e_convert || ((sql_exp*)e->r)->type == e_convert)) { + sql_rel *r = rel->r; + sql_exp *le = e->l, *re = e->r; + + /* if convert on left then find mul or div on right which increased scale! */ + if (le->type == e_convert && re->type == e_column && (e->flag == cmp_lt || e->flag == cmp_gt) && r && is_project(r->op)) { + sql_exp *nre = rel_find_exp(r, re); + sql_subtype *tt = exp_totype(le), *ft = exp_fromtype(le); + + if (nre && nre->type == e_func) { + sql_subfunc *f = nre->f; + + if (!f->func->s && !strcmp(f->func->base.name, "sql_mul")) { + list *args = nre->l; + sql_exp *ce = args->t->data; + sql_subtype *fst = exp_subtype(args->h->data); + + if (fst->scale && fst->scale == ft->scale && is_atom(ce->type) && ce->l) { + atom *a = ce->l; + int anti = is_anti(e); + sql_exp *arg1, *arg2; +#ifdef HAVE_HGE + hge val = 1; +#else + lng val = 1; +#endif + /* multiply with smallest value, then scale and (round) */ + int scale = (int) tt->scale - (int) ft->scale, rs = 0; + atom *na = reduce_scale(v->sql, a); + + if (na != a) { + rs = a->tpe.scale - na->tpe.scale; + ce->l = na; + } + scale -= rs; + + while (scale > 0) { + scale--; + val *= 10; + } + arg1 = re; +#ifdef HAVE_HGE + arg2 = exp_atom_hge(v->sql->sa, val); +#else + arg2 = exp_atom_lng(v->sql->sa, val); +#endif + if ((nre = rel_binop_(v->sql, NULL, arg1, arg2, "sys", "scale_down", card_value))) { + e = exp_compare(v->sql->sa, le->l, nre, e->flag); + if (anti) set_anti(e); + v->changes++; + } else { + v->sql->session->status = 0; + v->sql->errstr[0] = '\0'; + } + } + } + } + } } if (is_compare(e->type) && is_semantics(e) && (e->flag == cmp_equal || e->flag == cmp_notequal) && exp_is_null(e->r)) { /* simplify 'is null' predicates on constants */ @@ -8169,57 +8278,6 @@ exp_merge_range(visitor *v, sql_rel *rel return exps; } -/* - * Casting decimal values on both sides of a compare expression is expensive, - * both in preformance (cpu cost) and memory requirements (need for large - * types). - */ - -#define reduce_scale_tpe(tpe, uval) \ - do { \ - tpe v = uval; \ - if (v != 0) { \ - while( (v/10)*10 == v ) { \ - i++; \ - v /= 10; \ - } \ - nval = v; \ - } \ - } while (0) - -static atom * -reduce_scale(mvc *sql, atom *a) -{ - int i = 0; - atom *na = a; -#ifdef HAVE_HGE - hge nval = 0; -#else - lng nval = 0; -#endif - -#ifdef HAVE_HGE - if (a->data.vtype == TYPE_hge) { - reduce_scale_tpe(hge, a->data.val.hval); - } else -#endif - if (a->data.vtype == TYPE_lng) { - reduce_scale_tpe(lng, a->data.val.lval); - } else if (a->data.vtype == TYPE_int) { - reduce_scale_tpe(int, a->data.val.ival); - } else if (a->data.vtype == TYPE_sht) { - reduce_scale_tpe(sht, a->data.val.shval); - } else if (a->data.vtype == TYPE_bte) { - reduce_scale_tpe(bte, a->data.val.btval); - } - if (i) { - na = atom_int(sql->sa, &a->tpe, nval); - if (na->tpe.scale) - na->tpe.scale -= i; - } - return na; -} - static sql_rel * rel_project_reduce_casts(visitor *v, sql_rel *rel) { @@ -8266,88 +8324,6 @@ rel_project_reduce_casts(visitor *v, sql return rel; } -static inline sql_rel * -rel_reduce_casts(visitor *v, sql_rel *rel) -{ - list *exps = rel->exps; - assert(!list_empty(rel->exps)); - - for (node *n=exps->h; n; n = n->next) { - sql_exp *e = n->data; - sql_exp *le = e->l; - sql_exp *re = e->r; - - /* handle the and's in the or lists */ - if (e->type != e_cmp || !is_theta_exp(e->flag) || e->f) - continue; - /* rewrite e if left or right is a cast */ - if (le->type == e_convert || re->type == e_convert) { - sql_rel *r = rel->r; - - /* if convert on left then find - * mul or div on right which increased - * scale! - */ - if (le->type == e_convert && re->type == e_column && (e->flag == cmp_lt || e->flag == cmp_gt) && r && is_project(r->op)) { - sql_exp *nre = rel_find_exp(r, re); - sql_subtype *tt = exp_totype(le); - sql_subtype *ft = exp_fromtype(le); - - if (nre && nre->type == e_func) { - sql_subfunc *f = nre->f; - - if (!f->func->s && !strcmp(f->func->base.name, "sql_mul")) { - list *args = nre->l; - sql_exp *ce = args->t->data; - sql_subtype *fst = exp_subtype(args->h->data); - - if (fst->scale && fst->scale == ft->scale && is_atom(ce->type) && ce->l) { - atom *a = ce->l; - int anti = is_anti(e); - sql_exp *arg1, *arg2; -#ifdef HAVE_HGE - hge val = 1; -#else - lng val = 1; -#endif - /* multiply with smallest value, then scale and (round) */ - int scale = (int) tt->scale - (int) ft->scale, rs = 0; - atom *na = reduce_scale(v->sql, a); _______________________________________________ checkin-list mailing list [email protected] https://www.monetdb.org/mailman/listinfo/checkin-list
