Changeset: 6dd1a04a34ce for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6dd1a04a34ce Modified Files: sql/backends/monet5/sql_gencode.c sql/backends/monet5/sql_statement.c sql/common/sql_types.c sql/server/rel_exp.c sql/server/rel_exp.h sql/server/rel_optimizer.c sql/server/rel_rel.c sql/server/rel_select.c sql/test/BugTracker-2016/Tests/column_alias_in_where_clause.Bug-3947.stable.out sql/test/SQLancer/Tests/sqlancer03.stable.out sql/test/emptydb/Tests/check.stable.out sql/test/emptydb/Tests/check.stable.out.32bit sql/test/emptydb/Tests/check.stable.out.int128 sql/test/miscellaneous/Tests/simple_plans.stable.out sql/test/sys-schema/Tests/systemfunctions.stable.out sql/test/sys-schema/Tests/systemfunctions.stable.out.int128 Branch: oscar Log Message:
Mergws with Jun2020 diffs (truncated from 1386 to 300 lines): diff --git a/sql/backends/monet5/sql_statement.c b/sql/backends/monet5/sql_statement.c --- a/sql/backends/monet5/sql_statement.c +++ b/sql/backends/monet5/sql_statement.c @@ -3113,77 +3113,120 @@ stmt_Nop(backend *be, stmt *ops, sql_sub } } - if (backend_create_subfunc(be, f, ops->op4.lval) < 0) - return NULL; - mod = sql_func_mod(f->func); - fimp = sql_func_imp(f->func); - if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) { - sql_subtype *res = f->res->h->data; - fimp = convertMultiplexFcn(fimp); - q = NULL; - if (strcmp(fimp, "rotate_xor_hash") == 0 && - strcmp(mod, calcRef) == 0 && - (q = newStmt(mb, mkeyRef, bulk_rotate_xor_hashRef)) == NULL) - return NULL; - if (!q) { - if (f->func->type == F_UNION) - q = newStmt(mb, batmalRef, multiplexRef); - else - q = newStmt(mb, malRef, multiplexRef); - if (q == NULL) - return NULL; - setVarType(mb, getArg(q, 0), newBatType(res->type->localtype)); - setVarUDFtype(mb, getArg(q, 0)); - q = pushStr(mb, q, mod); - q = pushStr(mb, q, fimp); - } else { - setVarType(mb, getArg(q, 0), newBatType(res->type->localtype)); - setVarUDFtype(mb, getArg(q, 0)); + /* handle coalesce and nullif */ + if (list_length(ops->op4.lval) == 2 && + f->func->mod && strcmp(f->func->mod, "") == 0 && f->func->imp && strcmp(f->func->imp, "") == 0) { + stmt *e1 = ops->op4.lval->h->data; + stmt *e2 = ops->op4.lval->h->next->data; + int nrcols = 0; + + nrcols = e1->nrcols>e2->nrcols ? e1->nrcols:e2->nrcols; + /* nrcols */ + //coalesce(e1,e2) -> ifthenelse(not(isnil(e1)),e1,e2) + if (strcmp(f->func->base.name, "coalesce") == 0) { + str mod = (!nrcols)?calcRef:batcalcRef; + q = newStmt(mb, e1->nrcols?mod:calcRef, "isnil"); + q = pushArgument(mb, q, e1->nr); + int nr = getDestVar(q); + + q = newStmt(mb, e1->nrcols?mod:calcRef, "not"); + q = pushArgument(mb, q, nr); + nr = getDestVar(q); + + q = newStmt(mb, mod, "ifthenelse"); + q = pushArgument(mb, q, nr); + q = pushArgument(mb, q, e1->nr); + q = pushArgument(mb, q, e2->nr); } - } else { - fimp = convertOperator(fimp); - q = newStmt(mb, mod, fimp); - - if (f->res && list_length(f->res)) { - sql_subtype *res = f->res->h->data; - - setVarType(mb, getArg(q, 0), res->type->localtype); - setVarUDFtype(mb, getArg(q, 0)); + //nullif(e1,e2) -> ifthenelse(e1==e2),NULL,e1) + if (strcmp(f->func->base.name, "nullif") == 0) { + str mod = (!nrcols)?calcRef:batcalcRef; + sql_subtype *t = tail_type(e1); + int tt = t->type->localtype; + q = newStmt(mb, mod, "=="); + q = pushArgument(mb, q, e1->nr); + q = pushArgument(mb, q, e2->nr); + int nr = getDestVar(q); + + q = newStmt(mb, mod, "ifthenelse"); + q = pushArgument(mb, q, nr); + q = pushNil(mb, q, tt); + q = pushArgument(mb, q, e1->nr); } } - if (LANG_EXT(f->func->lang)) - q = pushPtr(mb, q, f); - if (f->func->lang == FUNC_LANG_C) { - q = pushBit(mb, q, 0); - } else if (f->func->lang == FUNC_LANG_CPP) { - q = pushBit(mb, q, 1); - } - if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY || - f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) { - q = pushStr(mb, q, f->func->query); - } - /* first dynamic output of copy* functions */ - if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL)) - q = table_func_create_result(mb, q, f->func, f->res); - if (list_length(ops->op4.lval)) - tpe = tail_type(ops->op4.lval->h->data); - if (strcmp(fimp, "round") == 0 && tpe && tpe->type->eclass == EC_DEC) - special = 1; - - for (n = ops->op4.lval->h; n; n = n->next) { - stmt *op = n->data; - - if (!op) - q = pushNil(mb, q, TYPE_bat); - else - q = pushArgument(mb, q, op->nr); - if (op && special) { - q = pushInt(mb, q, tpe->digits); - setVarUDFtype(mb, getArg(q, q->argc-1)); - q = pushInt(mb, q, tpe->scale); - setVarUDFtype(mb, getArg(q, q->argc-1)); + if (!q) { + if (backend_create_subfunc(be, f, ops->op4.lval) < 0) + return NULL; + mod = sql_func_mod(f->func); + fimp = sql_func_imp(f->func); + if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) { + sql_subtype *res = f->res->h->data; + fimp = convertMultiplexFcn(fimp); + q = NULL; + if (strcmp(fimp, "rotate_xor_hash") == 0 && + strcmp(mod, calcRef) == 0 && + (q = newStmt(mb, mkeyRef, bulk_rotate_xor_hashRef)) == NULL) + return NULL; + if (!q) { + if (f->func->type == F_UNION) + q = newStmt(mb, batmalRef, multiplexRef); + else + q = newStmt(mb, malRef, multiplexRef); + if (q == NULL) + return NULL; + setVarType(mb, getArg(q, 0), newBatType(res->type->localtype)); + setVarUDFtype(mb, getArg(q, 0)); + q = pushStr(mb, q, mod); + q = pushStr(mb, q, fimp); + } else { + setVarType(mb, getArg(q, 0), newBatType(res->type->localtype)); + setVarUDFtype(mb, getArg(q, 0)); + } + } else { + fimp = convertOperator(fimp); + q = newStmt(mb, mod, fimp); + + if (f->res && list_length(f->res)) { + sql_subtype *res = f->res->h->data; + + setVarType(mb, getArg(q, 0), res->type->localtype); + setVarUDFtype(mb, getArg(q, 0)); + } } - special = 0; + if (LANG_EXT(f->func->lang)) + q = pushPtr(mb, q, f); + if (f->func->lang == FUNC_LANG_C) { + q = pushBit(mb, q, 0); + } else if (f->func->lang == FUNC_LANG_CPP) { + q = pushBit(mb, q, 1); + } + if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY || + f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) { + q = pushStr(mb, q, f->func->query); + } + /* first dynamic output of copy* functions */ + if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL)) + q = table_func_create_result(mb, q, f->func, f->res); + if (list_length(ops->op4.lval)) + tpe = tail_type(ops->op4.lval->h->data); + if (strcmp(fimp, "round") == 0 && tpe && tpe->type->eclass == EC_DEC) + special = 1; + + for (n = ops->op4.lval->h; n; n = n->next) { + stmt *op = n->data; + + if (!op) + q = pushNil(mb, q, TYPE_bat); + else + q = pushArgument(mb, q, op->nr); + if (op && special) { + q = pushInt(mb, q, tpe->digits); + setVarUDFtype(mb, getArg(q, q->argc-1)); + q = pushInt(mb, q, tpe->scale); + setVarUDFtype(mb, getArg(q, q->argc-1)); + } + special = 0; + } } if (q) { 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 @@ -1307,6 +1307,9 @@ sqltypeinit( sql_allocator *sa) sql_create_func(sa, "least", "calc", "min_no_nil", FALSE, FALSE, SCALE_FIX, 0, ANY, 2, ANY, ANY); sql_create_func(sa, "greatest", "calc", "max_no_nil", FALSE, 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 */ + 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); /* sum for numerical and decimals */ sql_create_aggr(sa, "sum", "aggr", "sum", FALSE, LargestINT, 1, BTE); diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c --- a/sql/server/rel_exp.c +++ b/sql/server/rel_exp.c @@ -1921,6 +1921,20 @@ exps_have_rel_exp( list *exps) return 0; } +int +exps_have_func(list *exps) +{ + if (list_empty(exps)) + return 0; + for(node *n=exps->h; n; n=n->next) { + sql_exp *e = n->data; + + if (exp_has_func(e)) + return 1; + } + return 0; +} + static sql_rel * exps_rel_get_rel(sql_allocator *sa, list *exps ) { diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h --- a/sql/server/rel_exp.h +++ b/sql/server/rel_exp.h @@ -151,6 +151,7 @@ extern int exp_is_null(mvc *sql, sql_exp extern int exp_is_rel(sql_exp *e); extern int exp_has_rel(sql_exp *e); extern int exps_have_rel_exp(list *exps); +extern int exps_have_func(list *exps); extern sql_rel *exp_rel_get_rel(sql_allocator *sa, sql_exp *e); extern sql_exp *exp_rel_update_exp(mvc *sql, sql_exp *e); extern sql_exp *exp_rel_label(mvc *sql, sql_exp *e); 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 @@ -2829,20 +2829,6 @@ rel_merge_projects(visitor *v, sql_rel * all = 0; break; } - /* - if (ne && ne->type == e_column) { - sql_exp *nne = NULL; - - if (ne->l) - nne = exps_bind_column2(rel->exps, ne->l, ne->r); - if (!nne && !ne->l) - nne = exps_bind_column(rel->exps, ne->r, NULL, 1); - if (nne && ne != nne && nne != e) { - all = 0; - break; - } - } - */ if (ne) { if (exp_name(e)) exp_prop_alias(v->sql->sa, ne, e); @@ -2928,6 +2914,11 @@ exp_simplify_math( mvc *sql, sql_exp *e, * min_no_nil or max_no_nil), in which case we * ignore the NULL and return the other * value */ + + /* for both nullif and coalesce don't rewrite the NULL handling */ + if (f && f->func && f->func->imp && strcmp(f->func->imp, "") == 0) + return e; + if (exp_is_atom(le) && exp_is_null(sql, le)) { (*changes)++; if (f && f->func && f->func->imp && strstr(f->func->imp, "_no_nil") != NULL) { @@ -4477,7 +4468,7 @@ rel_push_select_down(visitor *v, sql_rel /* merge 2 selects */ r = rel->l; - if (is_select(rel->op) && r && r->exps && is_select(r->op) && !(rel_is_ref(r))) { + if (is_select(rel->op) && r && r->exps && is_select(r->op) && !(rel_is_ref(r)) && !exps_have_func(rel->exps)) { (void)list_merge(r->exps, rel->exps, (fdup)NULL); rel->l = NULL; rel_destroy(rel); @@ -5520,7 +5511,7 @@ rel_push_project_down(visitor *v, sql_re if (rel_is_ref(l)) return rel; - if (is_basetable(l->op)) { + if (is_base(l->op)) { if (list_check_prop_all(rel->exps, (prop_check_func)&exp_is_useless_rename)) { /* TODO reduce list (those in the project + internal) */ rel->l = NULL; @@ -6675,7 +6666,7 @@ exp_mark_used(sql_rel *subrel, sql_exp * break; } if (ne && e != ne) { - if (!local_proj || (has_label(ne) || (ne->alias.rname && ne->alias.rname[0] == '%'))) + if (!local_proj || (has_label(ne) || (ne->alias.rname && ne->alias.rname[0] == '%')) || (subrel->l && !rel_find_exp(subrel->l, e))) ne->used = 1; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list