Changeset: 6e01d555b38d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/6e01d555b38d
Modified Files:
sql/server/rel_exp.c
sql/server/rel_exp.h
sql/server/rel_optimizer.c
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/test/SQLancer/Tests/sqlancer18.test
Branch: Jan2022
Log Message:
make sure we know on which relation we need to group (ie the outer or the
inner).
If unclear and within the where, we should give an error.
diffs (truncated from 316 to 300 lines):
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
@@ -1541,20 +1541,20 @@ distinct_rel(sql_exp *e, const char **rn
}
int
-rel_has_exp(sql_rel *rel, sql_exp *e)
+rel_has_exp(sql_rel *rel, sql_exp *e, bool subexp)
{
- if (rel_find_exp(rel, e) != NULL)
+ if (rel_find_exp_and_corresponding_rel(rel, e, subexp, NULL, NULL))
return 0;
return -1;
}
int
-rel_has_exps(sql_rel *rel, list *exps)
+rel_has_exps(sql_rel *rel, list *exps, bool subexp)
{
if (list_empty(exps))
return 0;
for (node *n = exps->h; n; n = n->next)
- if (rel_has_exp(rel, n->data) >= 0)
+ if (rel_has_exp(rel, n->data, subexp) >= 0)
return 0;
return -1;
}
@@ -1565,15 +1565,21 @@ rel_has_all_exps(sql_rel *rel, list *exp
if (list_empty(exps))
return 1;
for (node *n = exps->h; n; n = n->next)
- if (rel_has_exp(rel, n->data) < 0)
+ if (rel_has_exp(rel, n->data, false) < 0)
return 0;
return 1;
}
+static int
+rel_has_exp2(sql_rel *rel, sql_exp *e)
+{
+ return rel_has_exp(rel, e, false);
+}
+
sql_rel *
find_rel(list *rels, sql_exp *e)
{
- node *n = list_find(rels, e, (fcmp)&rel_has_exp);
+ node *n = list_find(rels, e, (fcmp)&rel_has_exp2);
if (n)
return n->data;
return NULL;
@@ -1586,7 +1592,7 @@ find_one_rel(list *rels, sql_exp *e)
sql_rel *fnd = NULL;
for(n = rels->h; n; n = n->next) {
- if (rel_has_exp(n->data, e) == 0) {
+ if (rel_has_exp(n->data, e, false) == 0) {
if (fnd)
return NULL;
fnd = n->data;
@@ -1658,7 +1664,7 @@ exps_find_prop(list *exps, rel_prop kind
}
static sql_exp *
-rel_find_exp_and_corresponding_rel_(sql_rel *rel, sql_exp *e, sql_rel **res)
+rel_find_exp_and_corresponding_rel_(sql_rel *rel, sql_exp *e, bool subexp,
sql_rel **res)
{
sql_exp *ne = NULL;
@@ -1683,7 +1689,7 @@ rel_find_exp_and_corresponding_rel_(sql_
*res = rel;
return ne;
case e_convert:
- return rel_find_exp_and_corresponding_rel_(rel, e->l, res);
+ return rel_find_exp_and_corresponding_rel_(rel, e->l, subexp,
res);
case e_aggr:
case e_func:
if (e->l) {
@@ -1691,8 +1697,10 @@ rel_find_exp_and_corresponding_rel_(sql_
node *n = l->h;
ne = n->data;
- while (ne != NULL && n != NULL) {
- ne = rel_find_exp_and_corresponding_rel_(rel,
n->data, res);
+ while ((subexp || ne != NULL) && n != NULL) {
+ ne = rel_find_exp_and_corresponding_rel_(rel,
n->data, subexp, res);
+ if (subexp && ne)
+ break;
n = n->next;
}
return ne;
@@ -1708,8 +1716,10 @@ rel_find_exp_and_corresponding_rel_(sql_
node *n = l->h;
ne = n->data;
- while (ne != NULL && n != NULL) {
- ne = rel_find_exp_and_corresponding_rel_(rel,
n->data, res);
+ while ((subexp || ne != NULL) && n != NULL) {
+ ne = rel_find_exp_and_corresponding_rel_(rel,
n->data, subexp, res);
+ if (subexp && ne)
+ break;
n = n->next;
}
return ne;
@@ -1720,9 +1730,9 @@ rel_find_exp_and_corresponding_rel_(sql_
}
sql_exp *
-rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e, sql_rel **res,
bool *under_join)
+rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e, bool subexp,
sql_rel **res, bool *under_join)
{
- sql_exp *ne = rel_find_exp_and_corresponding_rel_(rel, e, res);
+ sql_exp *ne = rel_find_exp_and_corresponding_rel_(rel, e, subexp, res);
if (rel && !ne) {
switch(rel->op) {
@@ -1732,9 +1742,9 @@ rel_find_exp_and_corresponding_rel(sql_r
case op_join:
case op_semi:
case op_anti:
- ne = rel_find_exp_and_corresponding_rel(rel->l, e, res,
under_join);
+ ne = rel_find_exp_and_corresponding_rel(rel->l, e,
subexp, res, under_join);
if (!ne && is_join(rel->op))
- ne = rel_find_exp_and_corresponding_rel(rel->r,
e, res, under_join);
+ ne = rel_find_exp_and_corresponding_rel(rel->r,
e, subexp, res, under_join);
if (ne && under_join)
*under_join = true;
break;
@@ -1743,7 +1753,7 @@ rel_find_exp_and_corresponding_rel(sql_r
break;
default:
if (!is_project(rel->op) && rel->l)
- ne = rel_find_exp_and_corresponding_rel(rel->l,
e, res, under_join);
+ ne = rel_find_exp_and_corresponding_rel(rel->l,
e, subexp, res, under_join);
}
}
return ne;
@@ -1752,7 +1762,7 @@ rel_find_exp_and_corresponding_rel(sql_r
sql_exp *
rel_find_exp(sql_rel *rel, sql_exp *e)
{
- return rel_find_exp_and_corresponding_rel(rel, e, NULL, NULL);
+ return rel_find_exp_and_corresponding_rel(rel, e, false, NULL, NULL);
}
int
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
@@ -129,7 +129,7 @@ extern unsigned int exp_card(sql_exp *e)
extern const char *exp_find_rel_name(sql_exp *e);
extern sql_exp *rel_find_exp(sql_rel *rel, sql_exp *e);
-extern sql_exp *rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e,
sql_rel **res, bool *under_join);
+extern sql_exp *rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e,
bool subexp, sql_rel **res, bool *under_join);
extern int exp_cmp( sql_exp *e1, sql_exp *e2);
extern int exp_equal( sql_exp *e1, sql_exp *e2);
@@ -170,10 +170,10 @@ extern int exp_has_sideeffect(sql_exp *e
extern sql_exp *exps_find_prop(list *exps, rel_prop kind);
-/* returns 0 when the relation contain the passed expression else < 0 */
-extern int rel_has_exp(sql_rel *rel, sql_exp *e);
-/* return 0 when the relation contain atleast one of the passed expressions
else < 0 */
-extern int rel_has_exps(sql_rel *rel, list *e);
+/* returns 0 when the relation contain the passed expression (or sub
expressions if subexp is set) else < 0 */
+extern int rel_has_exp(sql_rel *rel, sql_exp *e, bool subexp);
+/* return 0 when the relation contain atleast one of the passed expressions
(or sub expressions if subexp is set) else < 0 */
+extern int rel_has_exps(sql_rel *rel, list *e, bool subexp);
/* return 1 when the relation contains all of the passed expressions else 0 */
extern int rel_has_all_exps(sql_rel *rel, list *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
@@ -386,7 +386,7 @@ static sql_exp *
joinexp_col(sql_exp *e, sql_rel *r)
{
if (e->type == e_cmp) {
- if (rel_has_exp(r, e->l) >= 0)
+ if (rel_has_exp(r, e->l, false) >= 0)
return e->l;
return e->r;
}
@@ -394,6 +394,12 @@ joinexp_col(sql_exp *e, sql_rel *r)
return NULL;
}
+static int
+rel_has_exp2(sql_rel *r, sql_exp *e)
+{
+ return rel_has_exp(r, e, false);
+}
+
static sql_column *
table_colexp(sql_exp *e, sql_rel *r)
{
@@ -827,8 +833,8 @@ order_joins(visitor *v, list *rels, list
node *ln, *rn, *en;
cje = djn->data;
- ln = list_find(n_rels, cje->l, (fcmp)&rel_has_exp);
- rn = list_find(n_rels, cje->r, (fcmp)&rel_has_exp);
+ ln = list_find(n_rels, cje->l, (fcmp)&rel_has_exp2);
+ rn = list_find(n_rels, cje->r, (fcmp)&rel_has_exp2);
if (ln && rn) {
assert(0);
@@ -992,7 +998,7 @@ push_in_join_down(mvc *sql, list *rels,
if (e->type == e_cmp && e->flag ==
cmp_equal) {
/* in values are on
the right of the join */
- if (rel_has_exp(r, e->r) >= 0)
+ if (rel_has_exp(r, e->r, false)
>= 0)
je = e;
}
}
@@ -4293,7 +4299,7 @@ gen_push_groupby_down(mvc *sql, sql_rel
if (exp_is_atom(ce))
list_append(aliases, ce);
else if (ce->type == e_column) {
- if (rel_has_exp(cl, ce) == 0) /* collect
aliases outside groupby */
+ if (rel_has_exp(cl, ce, false) == 0) /* collect
aliases outside groupby */
list_append(aliases, ce);
else
list_append(aggrs, ce);
@@ -4301,7 +4307,7 @@ gen_push_groupby_down(mvc *sql, sql_rel
list *args = ce->l;
/* check args are part of left/right */
- if (!list_empty(args) && rel_has_exps(cl, args)
== 0)
+ if (!list_empty(args) && rel_has_exps(cl, args,
false) == 0)
return rel;
if (rel->op != op_join && exp_aggr_is_count(ce))
ce->p = prop_create(sql->sa,
PROP_COUNT, ce->p);
@@ -5283,7 +5289,7 @@ find_projection_for_join2semi(sql_rel *r
return has_nil(e) ?
MAY_HAVE_DUPLICATE_NULLS : ALL_VALUES_DISTINCT;
if ((is_simple_project(rel->op) ||
is_groupby(rel->op) || is_inter(rel->op) || is_except(rel->op)) &&
- (found =
rel_find_exp_and_corresponding_rel(rel->l, e, &res, &underjoin)) && !underjoin)
{ /* grouping column on inner relation */
+ (found =
rel_find_exp_and_corresponding_rel(rel->l, e, false, &res, &underjoin)) &&
!underjoin) { /* grouping column on inner relation */
if (need_distinct(res) &&
list_length(res->exps) == 1)
return ALL_VALUES_DISTINCT;
if (is_unique(found))
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
@@ -3395,7 +3395,7 @@ static sql_exp *
sql_rel *groupby = rel ? *rel : NULL, *sel = NULL, *gr, *og = NULL,
*res = groupby;
sql_rel *subquery = NULL;
list *exps = NULL;
- bool is_grouping = !strcmp(aname, "grouping"), has_args = false, found
= false;
+ bool is_grouping = !strcmp(aname, "grouping"), has_args = false, found
= false, used_rel = false;
if (!query_has_outer(query)) {
if (!groupby) {
@@ -3443,6 +3443,7 @@ static sql_exp *
if (!e)
return NULL;
+ used_rel |= (rel_has_exp(gl, e, true) == 0);
has_args = true;
if (gl && gl != ogl) {
if (gl->grouped) {
@@ -3506,6 +3507,9 @@ static sql_exp *
return
sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped
column \"%s.%s\" from outer query", exp_relname(e), exp_name(e));
return
sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped
column from outer query");
}
+ } else if (!used_rel &&
is_sql_where(of)) {
+ char *uaname =
SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
+ return sql_error(sql,
02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause",
toUpperCopy(uaname, aname));
} else if (!is_sql_aggr(of)) {
set_outer(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
@@ -1945,9 +1945,9 @@ exp_reset_card_and_freevar_set_physical_
sql_exp *le = NULL, *re = NULL;
bool underjoinl = false, underjoinr = false;
- le = rel_find_exp_and_corresponding_rel(rel->l, e,
NULL, &underjoinl);
+ le = rel_find_exp_and_corresponding_rel(rel->l, e,
false, NULL, &underjoinl);
if (!is_simple_project(rel->op) && !is_inter(rel->op)
&& !is_except(rel->op) && !is_semi(rel->op) && rel->r) {
- re = rel_find_exp_and_corresponding_rel(rel->r,
e, NULL, &underjoinr);
+ re = rel_find_exp_and_corresponding_rel(rel->r,
e, false, NULL, &underjoinr);
/* if the expression is found under a join, the
cardinality expands to multi */
e->card =
MAX(le?underjoinl?CARD_MULTI:le->card:CARD_ATOM,
re?underjoinr?CARD_MULTI:re->card:CARD_ATOM);
} else if (e->card == CARD_ATOM) { /* unnested columns
vs atoms */
diff --git a/sql/test/SQLancer/Tests/sqlancer18.test
b/sql/test/SQLancer/Tests/sqlancer18.test
--- a/sql/test/SQLancer/Tests/sqlancer18.test
+++ b/sql/test/SQLancer/Tests/sqlancer18.test
@@ -672,17 +672,10 @@ statement ok
create or replace view v102(vc0) as (select 1 from v101)
statement ok
-savepoint sp1
-
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list