Changeset: c063a779dde4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c063a779dde4
Modified Files:
sql/server/rel_rel.c
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/test/BugTracker-2017/Tests/limit.Bug-6322.stable.out
sql/test/BugTracker-2017/Tests/push_subslice.Bug-6322.stable.out
sql/test/mergetables/Tests/sqlsmith-exists.stable.out
sql/test/mergetables/Tests/sqlsmith-exists2.stable.out
sql/test/subquery/Tests/subquery3.stable.err
Branch: default
Log Message:
fix output of sqlsmith-exists2 (ie removed too early and/or optimization)
added checks for aggregation in group by and nested aggregation (without
correlation)
diffs (truncated from 338 to 300 lines):
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -2048,6 +2048,11 @@ rel_visitor(mvc *sql, sql_rel *rel, rel_
if (!rel)
return rel;
+ if (rel->exps && (rel->exps = exps_rel_visitor(sql, rel->exps,
rel_rewriter)) == NULL)
+ return NULL;
+ if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r &&
(rel->r = exps_rel_visitor(sql, rel->r, rel_rewriter)) == NULL)
+ return NULL;
+
switch(rel->op){
case op_basetable:
case op_table:
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -2392,54 +2392,12 @@ rel_logical_exp(sql_query *query, sql_re
}
case SQL_AND:
{
- /* split into 2 lists, simle logical expressions and or's */
- list *nors = sa_list(sql->sa);
- list *ors = sa_list(sql->sa);
-
symbol *lo = sc->data.lval->h->data.sym;
symbol *ro = sc->data.lval->h->next->data.sym;
- node *n;
-
- while (lo->token == SQL_AND) {
- symbol *s;
-
- sc = lo;
- lo = sc->data.lval->h->data.sym;
- s = sc->data.lval->h->next->data.sym;
-
- if (s->token != SQL_OR)
- list_prepend(nors, s);
- else
- list_prepend(ors, s);
- }
- if (lo->token != SQL_OR)
- list_prepend(nors, lo);
- else
- list_prepend(ors, lo);
- if (ro->token != SQL_OR)
- append(nors, ro);
- else
- append(ors, ro);
-
- for(n=nors->h; n; n = n->next) {
- symbol *lo = n->data;
- rel = rel_logical_exp(query, rel, lo, f);
- if (!rel)
- return NULL;
- }
- for(n=ors->h; n; n = n->next) {
- symbol *lo = n->data;
- rel = rel_logical_exp(query, rel, lo, f);
- if (!rel)
- return NULL;
- }
- return rel;
- /*
rel = rel_logical_exp(query, rel, lo, f);
if (!rel)
return NULL;
return rel_logical_exp(query, rel, ro, f);
- */
}
case SQL_FILTER:
/* [ x,..] filter [ y,..] */
@@ -3243,6 +3201,7 @@ static sql_exp *
exps = sa_list(sql->sa);
if (args && args->data.sym) {
+ int all_aggr = query_has_outer(query);
all_freevar = 1;
for ( ; args; args = args->next ) {
int base = (!groupby || !is_project(groupby->op) ||
is_base(groupby->op) || is_processed(groupby));
@@ -3257,10 +3216,27 @@ static sql_exp *
}
if (!e || !exp_subtype(e)) /* we also do not expect
parameters here */
return NULL;
+ all_aggr &= (exp_card(e) <= CARD_AGGR &&
!exp_is_atom(e) && !is_func(e->type) && (!groupby->r ||
!exps_find_exp(groupby->r, e)));
has_freevar |= exp_has_freevar(sql, e);
all_freevar &= (is_freevar(e)>0);
list_append(exps, e);
}
+ if (all_aggr && !all_freevar) {
+ char *uaname = GDKmalloc(strlen(aname) + 1);
+ sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s:
aggregate functions cannot be nested",
+ uaname ? toUpperCopy(uaname, aname) :
aname);
+ if (uaname)
+ GDKfree(uaname);
+ return e;
+ }
+ if (is_sql_groupby(f) && !all_freevar) {
+ char *uaname = GDKmalloc(strlen(aname) + 1);
+ sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s:
aggregate function '%s' not allowed in GROUP BY clause",
+ uaname ?
toUpperCopy(uaname, aname) : aname, aname);
+ if (uaname)
+ GDKfree(uaname);
+ return e;
+ }
}
if (all_freevar) { /* case 2, ie use outer */
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -1501,6 +1501,71 @@ rewrite_exp_rel(mvc *sql, sql_rel *rel,
/* simplify expressions, such as not(not(x)) */
/* exp visitor */
+
+static list *
+exps_simplify_exp(mvc *sql, list *exps)
+{
+ if (list_empty(exps))
+ return exps;
+
+ int needed = 0;
+ for (node *n=exps->h; n && !needed; n = n->next) {
+ sql_exp *e = n->data;
+
+ needed = (exp_is_true(sql, e) || exp_is_false(sql, e) ||
(is_compare(e->type) && e->flag == cmp_or));
+ }
+ if (needed) {
+ list *nexps = sa_list(sql->sa);
+ sql->caching = 0;
+ for (node *n=exps->h; n; n = n->next) {
+ sql_exp *e = n->data;
+
+ /* TRUE or X -> TRUE
+ * FALSE or X -> X */
+ if (is_compare(e->type) && e->flag == cmp_or) {
+ list *l = e->l = exps_simplify_exp(sql, e->l);
+ list *r = e->r = exps_simplify_exp(sql, e->r);
+
+ if (list_length(l) == 1) {
+ sql_exp *ie = l->h->data;
+
+ if (exp_is_true(sql, ie)) {
+ continue;
+ } else if (exp_is_false(sql, ie)) {
+ nexps = list_merge(nexps, r,
(fdup)NULL);
+ continue;
+ }
+ } else if (list_length(l) == 0) { /* left is
true */
+ continue;
+ }
+ if (list_length(r) == 1) {
+ sql_exp *ie = r->h->data;
+
+ if (exp_is_true(sql, ie))
+ continue;
+ else if (exp_is_false(sql, ie)) {
+ nexps = list_merge(nexps, l,
(fdup)NULL);
+ continue;
+ }
+ } else if (list_length(r) == 0) { /* right is
true */
+ continue;
+ }
+ }
+ /* TRUE and X -> X */
+ if (exp_is_true(sql, e)) {
+ continue;
+ /* FALSE and X -> FALSE */
+ } else if (exp_is_false(sql, e)) {
+ return append(sa_list(sql->sa), e);
+ } else {
+ append(nexps, e);
+ }
+ }
+ return nexps;
+ }
+ return exps;
+}
+
static sql_exp *
rewrite_simplify_exp(mvc *sql, sql_rel *rel, sql_exp *e, int depth)
{
@@ -1540,7 +1605,8 @@ rewrite_simplify_exp(mvc *sql, sql_rel *
/* TRUE or X -> TRUE
* FALSE or X -> X */
if (is_compare(e->type) && e->flag == cmp_or) {
- list *l = e->l, *r = e->r;
+ list *l = e->l = exps_simplify_exp(sql, e->l);
+ list *r = e->r = exps_simplify_exp(sql, e->r);
sql->caching = 0;
if (list_length(l) == 1) {
@@ -1550,6 +1616,18 @@ rewrite_simplify_exp(mvc *sql, sql_rel *
return ie;
else if (exp_is_false(sql, ie) &&
list_length(r) == 1)
return r->h->data;
+ } else if (list_length(l) == 0) { /* left is true */
+ return exp_atom_bool(sql->sa, 1);
+ }
+ if (list_length(r) == 1) {
+ sql_exp *ie = r->h->data;
+
+ if (exp_is_true(sql, ie))
+ return ie;
+ else if (exp_is_false(sql, ie) &&
list_length(l) == 1)
+ return l->h->data;
+ } else if (list_length(r) == 0) { /* right is true */
+ return exp_atom_bool(sql->sa, 1);
}
}
}
@@ -1562,33 +1640,8 @@ rewrite_simplify(mvc *sql, sql_rel *rel)
if (!rel)
return rel;
- if (is_select(rel->op) && !list_empty(rel->exps)) {
- int needed = 0;
- for (node *n=rel->exps->h; n && !needed; n = n->next) {
- sql_exp *e = n->data;
-
- needed = (exp_is_true(sql, e) || exp_is_false(sql, e));
- }
- if (needed) {
- list *nexps = sa_list(sql->sa);
- sql->caching = 0;
- for (node *n=rel->exps->h; n; n = n->next) {
- sql_exp *e = n->data;
-
- /* TRUE and X -> X */
- if (exp_is_true(sql, e)) {
- continue;
- /* FALSE and X -> FALSE */
- } else if (exp_is_false(sql, e)) {
- rel->exps = append(sa_list(sql->sa), e);
- return rel;
- } else {
- append(nexps, e);
- }
- }
- rel->exps = nexps;
- }
- }
+ if ((is_select(rel->op) || is_join(rel->op)) && !list_empty(rel->exps))
+ rel->exps = exps_simplify_exp(sql, rel->exps);
return rel;
}
diff --git a/sql/test/BugTracker-2017/Tests/limit.Bug-6322.stable.out
b/sql/test/BugTracker-2017/Tests/limit.Bug-6322.stable.out
--- a/sql/test/BugTracker-2017/Tests/limit.Bug-6322.stable.out
+++ b/sql/test/BugTracker-2017/Tests/limit.Bug-6322.stable.out
@@ -39,7 +39,7 @@ stdout of test 'limit.Bug-6322` in direc
#where (true)
# or ((select pc from sys.tracelog)
# is not NULL);
-% . # table_name
+% sys. # table_name
% c2 # name
% int # type
% 2 # length
diff --git a/sql/test/BugTracker-2017/Tests/push_subslice.Bug-6322.stable.out
b/sql/test/BugTracker-2017/Tests/push_subslice.Bug-6322.stable.out
--- a/sql/test/BugTracker-2017/Tests/push_subslice.Bug-6322.stable.out
+++ b/sql/test/BugTracker-2017/Tests/push_subslice.Bug-6322.stable.out
@@ -47,7 +47,7 @@ stdout of test 'push_subslice.Bug-6322`
#where (true)
# or ((select pc from sys.tracelog)
# is not NULL);
-% . # table_name
+% sys. # table_name
% c2 # name
% int # type
% 4 # length
diff --git a/sql/test/mergetables/Tests/sqlsmith-exists.stable.out
b/sql/test/mergetables/Tests/sqlsmith-exists.stable.out
--- a/sql/test/mergetables/Tests/sqlsmith-exists.stable.out
+++ b/sql/test/mergetables/Tests/sqlsmith-exists.stable.out
@@ -72,7 +72,7 @@ stdout of test 'sqlsmith-exists` in dire
# ref_1.col5 as c12,
# ref_2.col3 as c13,
# case when exists (
-% ., ., ., . # table_name
+% sys., sys., ., sys. # table_name
% c0, c1, c2, c3 # name
% int, int, tinyint, int # type
% 1, 1, 1, 1 # length
@@ -459,7 +459,7 @@ stdout of test 'sqlsmith-exists` in dire
# ref_0.col1 AS c0
# ,89 AS c1
# ,ref_0.col2 AS c2
-% ., . # table_name
+% ., sys. # table_name
% c0, c1 # name
% varchar, varchar # type
% 0, 0 # length
diff --git a/sql/test/mergetables/Tests/sqlsmith-exists2.stable.out
b/sql/test/mergetables/Tests/sqlsmith-exists2.stable.out
--- a/sql/test/mergetables/Tests/sqlsmith-exists2.stable.out
+++ b/sql/test/mergetables/Tests/sqlsmith-exists2.stable.out
@@ -81,6 +81,9 @@ stdout of test 'sqlsmith-exists2` in dir
% c0 # name
% int # type
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list