Changeset: 830922be8989 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/830922be8989 Added Files: sql/server/rel_optimize_exps.c sql/server/rel_optimize_others.c sql/server/rel_optimize_proj.c sql/server/rel_optimize_sel.c sql/server/rel_optimizer_private.h Modified Files: sql/server/CMakeLists.txt sql/server/rel_optimizer.c sql/server/rel_optimizer.h sql/server/rel_rewriter.c sql/server/rel_rewriter.h sql/server/rel_unnest.c sql/test/Tests/keys.test Branch: sqloptimizer Log Message:
Splitting different SQL optimizers into different groups across multiple translation units. Creating a framework that will be used to time the SQL optimizers later. More is still needed. diffs (truncated from 18884 to 300 lines): diff --git a/sql/server/CMakeLists.txt b/sql/server/CMakeLists.txt --- a/sql/server/CMakeLists.txt +++ b/sql/server/CMakeLists.txt @@ -46,6 +46,10 @@ target_sources(sqlserver rel_rewriter.c rel_unnest.c rel_optimizer.c + rel_optimize_exps.c + rel_optimize_others.c + rel_optimize_proj.c + rel_optimize_sel.c rel_partition.c rel_planner.c rel_planner.h rel_distribute.c @@ -58,6 +62,7 @@ target_sources(sqlserver rel_basetable.h rel_unnest.h rel_optimizer.h + rel_optimizer_private.h rel_partition.h rel_distribute.h rel_prop.h diff --git a/sql/server/rel_optimize_exps.c b/sql/server/rel_optimize_exps.c new file mode 100644 --- /dev/null +++ b/sql/server/rel_optimize_exps.c @@ -0,0 +1,793 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V. + */ + +#include "monetdb_config.h" +#include "rel_optimizer.h" +#include "rel_optimizer_private.h" +#include "rel_rel.h" +#include "rel_basetable.h" +#include "rel_select.h" +#include "rel_exp.h" +#include "rel_prop.h" +#include "rel_dump.h" +#include "rel_rewriter.h" +#include "sql_mvc.h" + +static inline int +str_ends_with(const char *s, const char *suffix) +{ + size_t slen = strlen(s), suflen = strlen(suffix); + if (suflen > slen) + return 1; + return strncmp(s + slen - suflen, suffix, suflen); +} + +static sql_exp * +exp_simplify_math( mvc *sql, sql_exp *e, int *changes) +{ + if (e->type == e_func || e->type == e_aggr) { + list *l = e->l; + sql_subfunc *f = e->f; + node *n; + sql_exp *le; + + if (list_length(l) < 1) + return e; + + /* if the function has no null semantics we can return NULL if one of the arguments is NULL */ + if (!f->func->semantics && f->func->type != F_PROC) { + for (node *n = l->h ; n ; n = n->next) { + sql_exp *arg = n->data; + + if (exp_is_atom(arg) && exp_is_null(arg)) { + sql_exp *ne = exp_null(sql->sa, exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, ne, e); + return ne; + } + } + } + if (!f->func->s && list_length(l) == 2 && str_ends_with(sql_func_imp(f->func), "_no_nil") == 0) { + sql_exp *le = l->h->data; + sql_exp *re = l->h->next->data; + + /* if "_no_nil" is in the name of the + * implementation function (currently either + * min_no_nil or max_no_nil), in which case we + * ignore the NULL and return the other value */ + + if (exp_is_atom(le) && exp_is_null(le)) { + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, re, e); + return re; + } + if (exp_is_atom(re) && exp_is_null(re)) { + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, le, e); + return le; + } + } + + le = l->h->data; + if (!EC_COMPUTE(exp_subtype(le)->type->eclass) && exp_subtype(le)->type->eclass != EC_DEC) + return e; + + if (!f->func->s && !strcmp(f->func->base.name, "sql_mul") && list_length(l) == 2) { + sql_exp *le = l->h->data; + sql_exp *re = l->h->next->data; + sql_subtype *et = exp_subtype(e); + + /* 0*a = 0 */ + if (exp_is_atom(le) && exp_is_zero(le) && exp_is_atom(re) && exp_is_not_null(re)) { + (*changes)++; + le = exp_zero(sql->sa, et); + if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0) + le = exp_convert(sql->sa, le, exp_subtype(le), exp_subtype(e)); + if (exp_name(e)) + exp_prop_alias(sql->sa, le, e); + return le; + } + /* a*0 = 0 */ + if (exp_is_atom(re) && exp_is_zero(re) && exp_is_atom(le) && exp_is_not_null(le)) { + (*changes)++; + re = exp_zero(sql->sa, et); + if (subtype_cmp(exp_subtype(e), exp_subtype(re)) != 0) + re = exp_convert(sql->sa, re, exp_subtype(re), exp_subtype(e)); + if (exp_name(e)) + exp_prop_alias(sql->sa, re, e); + return re; + } + if (exp_is_atom(le) && exp_is_atom(re)) { + atom *la = exp_flatten(sql, true, le); + atom *ra = exp_flatten(sql, true, re); + + if (la && ra && subtype_cmp(atom_type(la), atom_type(ra)) == 0 && subtype_cmp(atom_type(la), exp_subtype(e)) == 0) { + atom *a = atom_mul(sql->sa, la, ra); + + if (a && (a = atom_cast(sql->sa, a, exp_subtype(e)))) { + sql_exp *ne = exp_atom(sql->sa, a); + if (subtype_cmp(exp_subtype(e), exp_subtype(ne)) != 0) + ne = exp_convert(sql->sa, ne, exp_subtype(ne), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, ne, e); + return ne; + } + } + } + /* change a*pow(a,n) or pow(a,n)*a into pow(a,n+1) */ + if (is_func(le->type)) { + list *l = le->l; + sql_subfunc *f = le->f; + + if (!f->func->s && !strcmp(f->func->base.name, "power") && list_length(l) == 2) { + sql_exp *lle = l->h->data; + sql_exp *lre = l->h->next->data; + if (exp_equal(re, lle)==0) { + atom *a = exp_value(sql, lre); + if (a && (a = atom_inc(sql->sa, a))) { + lre->l = a; + lre->r = NULL; + if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0) + le = exp_convert(sql->sa, le, exp_subtype(le), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, le, e); + return le; + } + } + } + if (!f->func->s && !strcmp(f->func->base.name, "sql_mul") && list_length(l) == 2) { + sql_exp *lle = l->h->data; + sql_exp *lre = l->h->next->data; + if (!exp_is_atom(lle) && exp_is_atom(lre) && exp_is_atom(re)) { + /* (x*c1)*c2 -> x * (c1*c2) */ + sql_exp *ne = NULL; + + if (!(le = rel_binop_(sql, NULL, lre, re, "sys", "sql_mul", card_value))) { + sql->session->status = 0; + sql->errstr[0] = '\0'; + return e; /* error, fallback to original expression */ + } + if (!(ne = rel_binop_(sql, NULL, lle, le, "sys", "sql_mul", card_value))) { + sql->session->status = 0; + sql->errstr[0] = '\0'; + return e; /* error, fallback to original expression */ + } + if (subtype_cmp(exp_subtype(e), exp_subtype(ne)) != 0) + ne = exp_convert(sql->sa, ne, exp_subtype(ne), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, ne, e); + return ne; + } + } + } + } + if (!f->func->s && !strcmp(f->func->base.name, "sql_add") && list_length(l) == 2) { + sql_exp *le = l->h->data; + sql_exp *re = l->h->next->data; + if (exp_is_atom(le) && exp_is_zero(le)) { + if (subtype_cmp(exp_subtype(e), exp_subtype(re)) != 0) + re = exp_convert(sql->sa, re, exp_subtype(re), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, re, e); + return re; + } + if (exp_is_atom(re) && exp_is_zero(re)) { + if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0) + le = exp_convert(sql->sa, le, exp_subtype(le), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, le, e); + return le; + } + if (exp_is_atom(le) && exp_is_atom(re)) { + atom *la = exp_flatten(sql, true, le); + atom *ra = exp_flatten(sql, true, re); + + if (la && ra) { + atom *a = atom_add(sql->sa, la, ra); + + if (a) { + sql_exp *ne = exp_atom(sql->sa, a); + if (subtype_cmp(exp_subtype(e), exp_subtype(ne)) != 0) + ne = exp_convert(sql->sa, ne, exp_subtype(ne), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, ne, e); + return ne; + } + } + } + if (is_func(le->type)) { + list *ll = le->l; + sql_subfunc *f = le->f; + if (!f->func->s && !strcmp(f->func->base.name, "sql_add") && list_length(ll) == 2) { + sql_exp *lle = ll->h->data; + sql_exp *lre = ll->h->next->data; + + if (exp_is_atom(lle) && exp_is_atom(lre)) + return e; + if (!exp_is_atom(re) && exp_is_atom(lre)) { + /* (x+c1)+y -> (x+y) + c1 */ + ll->h->next->data = re; + l->h->next->data = lre; + if (!(l->h->data = exp_simplify_math(sql, le, changes))) + return NULL; + (*changes)++; + return e; + } + if (exp_is_atom(re) && exp_is_atom(lre)) { + /* (x+c1)+c2 -> (c2+c1) + x */ + ll->h->data = re; + l->h->next->data = lle; + if (!(l->h->data = exp_simplify_math(sql, le, changes))) + return NULL; + (*changes)++; + return e; + } + } + } + } + if (!f->func->s && !strcmp(f->func->base.name, "sql_sub") && list_length(l) == 2) { + sql_exp *le = l->h->data; + sql_exp *re = l->h->next->data; + + if (exp_is_atom(le) && exp_is_atom(re)) { + atom *la = exp_flatten(sql, true, le); + atom *ra = exp_flatten(sql, true, re); + + if (la && ra) { + atom *a = atom_sub(sql->sa, la, ra); + + if (a) { + sql_exp *ne = exp_atom(sql->sa, a); + if (subtype_cmp(exp_subtype(e), exp_subtype(ne)) != 0) + ne = exp_convert(sql->sa, ne, exp_subtype(ne), exp_subtype(e)); + (*changes)++; + if (exp_name(e)) + exp_prop_alias(sql->sa, ne, e); + return ne; + } + } + } + if (exp_is_not_null(le) && exp_is_not_null(re) && exp_equal(le,re) == 0) { /* a - a = 0 */ + atom *a; + sql_exp *ne; + + if (exp_subtype(le)->type->eclass == EC_NUM) { + a = atom_int(sql->sa, exp_subtype(le), 0); + } else if (exp_subtype(le)->type->eclass == EC_FLT) { + a = atom_float(sql->sa, exp_subtype(le), 0); + } else { + return e; _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org