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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list