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

Reply via email to