Changeset: 0461e2869d91 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0461e2869d91
Modified Files:
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/server/rel_unnest.h
sql/test/Tests/hot-snapshot.py
sql/test/subquery/Tests/subquery3.stable.err
sql/test/subquery/Tests/subquery5.stable.err
Branch: scoping
Log Message:
Merged with default
diffs (truncated from 329 to 300 lines):
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
@@ -1194,7 +1194,7 @@ rel_column_ref(sql_query *query, sql_rel
if (exp)
break;
}
- if (exp && outer && outer->card <= CARD_AGGR &&
exp->card > CARD_AGGR && (!is_sql_aggr(f) || is_sql_farg(f)))
+ if (exp && outer && outer->card <= CARD_AGGR &&
exp->card > CARD_AGGR && !is_sql_aggr(f))
return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results
without an aggregate function", name);
if (exp && outer && !is_sql_aggr(f)) {
if (query_outer_used_exp( query, i, exp, f)) {
@@ -1258,7 +1258,7 @@ rel_column_ref(sql_query *query, sql_rel
if (exp)
break;
}
- if (exp && outer && outer->card <= CARD_AGGR &&
exp->card > CARD_AGGR && (!is_sql_aggr(f) || is_sql_farg(f)))
+ if (exp && outer && outer->card <= CARD_AGGR &&
exp->card > CARD_AGGR && !is_sql_aggr(f))
return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query
results without an aggregate function", tname, cname);
if (exp && outer && !is_sql_aggr(f)) {
if (query_outer_used_exp( query, i, exp, f)) {
@@ -3358,14 +3358,16 @@ static sql_exp *
exps = sa_list(sql->sa);
if (args && args->data.sym) {
- int ungrouped_col = -1, i, all_aggr = query_has_outer(query);
+ int i, all_aggr = query_has_outer(query);
+ bool found_nested_aggr = false;
+ list *ungrouped_cols = NULL;
+
all_freevar = 1;
- bool found_nested_aggr = false;
for (i = 0; args && args->data.sym; args = args->next, i++) {
int base = (!groupby || !is_project(groupby->op) ||
is_base(groupby->op) || is_processed(groupby));
- bool found_one = false;
- sql_rel *outer = NULL, *gl = base?groupby:groupby->l,
*ogl = gl; /* handle case of subqueries without correlation */
- sql_exp *e = rel_value_exp(query, &gl, args->data.sym,
(f | sql_aggr)& ~sql_farg, ek), *a = NULL;
+ sql_rel *gl = base?groupby:groupby->l, *ogl = gl; /*
handle case of subqueries without correlation */
+ sql_exp *e = rel_value_exp(query, &gl, args->data.sym,
(f | sql_aggr)& ~sql_farg, ek);
+ bool found_one_freevar = false;
has_args = true;
if (gl && gl != ogl) {
@@ -3393,38 +3395,15 @@ static sql_exp *
return e;
}
- if (is_freevar(e) && e->type == e_column) {
- if ((outer = query_fetch_outer(query,
is_freevar(e)-1))) {
- if ((a = rel_find_exp(outer, e)) &&
is_aggr(a->type))
- return sql_error(sql, 05,
SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested");
- }
- }
-
- if (all_aggr) {
- /* get expression from outer */
- int aggr = 0;
- if (a)
- aggr = is_aggr(a->type);
- else if (outer && outer->grouped)
- ungrouped_col = i;
- all_aggr &= aggr;
- } else {
- all_aggr &= (exp_card(e) <= CARD_AGGR &&
!exp_is_atom(e) && is_aggr(e->type) && !is_func(e->type) && (!groupby ||
!is_groupby(groupby->op) || !groupby->r || !exps_find_exp(groupby->r, e)));
- }
- all_freevar &= (exp_only_freevar(query, e, &found_one,
&found_nested_aggr) && found_one);
+ all_aggr &= (exp_card(e) <= CARD_AGGR &&
!exp_is_atom(e) && is_aggr(e->type) && !is_func(e->type) && (!groupby ||
!is_groupby(groupby->op) || !groupby->r || !exps_find_exp(groupby->r, e)));
+ exp_only_freevar(query, e, &all_freevar,
&found_one_freevar, &found_nested_aggr, &ungrouped_cols);
+ all_freevar &= found_one_freevar; /* no uncorrelated
variables must be found, plus at least one correlated variable to push this
aggregate to an outer query */
list_append(exps, e);
}
- if (all_freevar && (all_aggr || found_nested_aggr))
+ if (all_aggr || (all_freevar && found_nested_aggr))
return sql_error(sql, 05, SQLSTATE(42000) "SELECT:
aggregate function calls cannot be nested");
if (!all_freevar) {
- if (all_aggr) {
- 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;
- } else if (is_sql_groupby(f)) {
+ if (is_sql_groupby(f)) {
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);
@@ -3459,9 +3438,26 @@ static sql_exp *
if (uaname)
GDKfree(uaname);
return e;
- } else if (!all_aggr && ungrouped_col >= 0) {
- sql_exp *u = list_fetch(exps, ungrouped_col);
- return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer
query", exp_relname(u), exp_name(u));
+ } else if (!all_aggr && ungrouped_cols &&
!list_empty(ungrouped_cols)) {
+ for (node *n = ungrouped_cols->h ; n ; n =
n->next) {
+ sql_rel *outer;
+ sql_exp *e = (sql_exp*) n->data;
+
+ if ((outer = query_fetch_outer(query,
is_freevar(e)-1)) && outer->grouped) {
+ bool err = false, was_processed
= false;
+
+ if (is_processed(outer)) {
+ was_processed = true;
+ reset_processed(outer);
+ }
+ if (!is_groupby_col(outer, e))
+ err = true;
+ if (was_processed)
+ set_processed(outer);
+ if (err)
+ return sql_error(sql,
ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\"
from outer query", exp_relname(e), exp_name(e));
+ }
+ }
}
}
}
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
@@ -171,97 +171,109 @@ rel_has_freevar(mvc *sql, sql_rel *rel)
return 0;
}
-static int exps_only_freevar(sql_query *query, list *exps, bool *found_one,
bool *found_aggr);
-static int rel_only_freevar(sql_query *query, sql_rel *rel, bool *found_one,
bool *found_aggr);
+static void exps_only_freevar(sql_query *query, list *exps, unsigned int
*all_freevar, bool *found_one_freevar, bool *found_aggr, list **ungrouped_cols);
+static void rel_only_freevar(sql_query *query, sql_rel *rel, unsigned int
*all_freevar, bool *found_one_freevar, bool *found_aggr, list **ungrouped_cols);
-int /* look for expressions with either only freevars or atoms */
-exp_only_freevar(sql_query *query, sql_exp *e, bool *found_one, bool
*found_aggr)
+void /* look for expressions with either only freevars or atoms */
+exp_only_freevar(sql_query *query, sql_exp *e, unsigned int *all_freevar, bool
*found_one_freevar, bool *found_aggr, list **ungrouped_cols)
{
if (THRhighwater()) {
(void) sql_error(query->sql, 10, SQLSTATE(42000) "Query too
complex: running out of stack space");
- return 0;
+ return ;
}
if (is_freevar(e)) {
sql_rel *outer;
- sql_exp *a;
- *found_one = true;
+ *found_one_freevar = true;
if (e->type == e_column) {
if ((outer = query_fetch_outer(query,
is_freevar(e)-1))) {
- if ((a = rel_find_exp(outer, e)) &&
is_aggr(a->type))
+ sql_exp *a = rel_find_exp(outer, e);
+ if (a && is_aggr(a->type))
*found_aggr = true;
+ else {
+ if (!*ungrouped_cols)
+ *ungrouped_cols =
new_exp_list(query->sql->sa);
+ list_append(*ungrouped_cols, e);
+ }
}
}
- return 1;
+ return ;
}
switch(e->type) {
case e_cmp:
if (e->flag == cmp_or || e->flag == cmp_filter) {
- return (exps_only_freevar(query, e->l, found_one,
found_aggr) && exps_only_freevar(query, e->r, found_one, found_aggr));
+ exps_only_freevar(query, e->l, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ exps_only_freevar(query, e->r, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
} else if (e->flag == cmp_in || e->flag == cmp_notin) {
- return (exp_only_freevar(query, e->l, found_one,
found_aggr) && exps_only_freevar(query, e->r, found_one, found_aggr));
+ exp_only_freevar(query, e->l, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ exps_only_freevar(query, e->r, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
} else {
- return (exp_only_freevar(query, e->l, found_one,
found_aggr) && exp_only_freevar(query, e->r, found_one, found_aggr) &&
- (!e->f || (e->f &&
exp_only_freevar(query, e->f, found_one, found_aggr))));
+ exp_only_freevar(query, e->l, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ exp_only_freevar(query, e->r, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ if (e->f)
+ exp_only_freevar(query, e->f, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
}
+ break;
case e_convert:
- return exp_only_freevar(query, e->l, found_one, found_aggr);
+ exp_only_freevar(query, e->l, all_freevar, found_one_freevar,
found_aggr, ungrouped_cols);
+ break;
case e_func:
case e_aggr:
if (e->l)
- return exps_only_freevar(query, e->l, found_one,
found_aggr);
- return 1;
+ exps_only_freevar(query, e->l, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ break;
case e_psm:
if (exp_is_rel(e))
- return rel_only_freevar(query, e->l, found_one,
found_aggr);
- return 1;
+ rel_only_freevar(query, e->l, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ break;
case e_atom:
- return 1;
+ break;
case e_column:
- return 0;
+ *all_freevar = 0;
+ break;
}
- return 0;
}
-int
-exps_only_freevar(sql_query *query, list *exps, bool *found_one, bool
*found_aggr)
-{
- int all_freevar = 1;
-
- if (THRhighwater()) {
- (void) sql_error(query->sql, 10, SQLSTATE(42000) "Query too
complex: running out of stack space");
- return 0;
- }
- if (!exps)
- return 0;
- for (node *n = exps->h; n && all_freevar; n = n->next) {
- sql_exp *e = n->data;
- all_freevar &= exp_only_freevar(query, e, found_one,
found_aggr);
- }
- return all_freevar;
-}
-
-int
-rel_only_freevar(sql_query *query, sql_rel *rel, bool *found_one, bool
*found_aggr)
+void
+exps_only_freevar(sql_query *query, list *exps, unsigned int *all_freevar,
bool *found_one_freevar, bool *found_aggr, list **ungrouped_cols)
{
if (THRhighwater()) {
(void) sql_error(query->sql, 10, SQLSTATE(42000) "Query too
complex: running out of stack space");
- return 0;
+ return ;
+ }
+ if (!exps)
+ return ;
+ for (node *n = exps->h; n ; n = n->next)
+ exp_only_freevar(query, n->data, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+}
+
+void
+rel_only_freevar(sql_query *query, sql_rel *rel, unsigned int *all_freevar,
bool *found_one_freevar, bool *found_aggr, list **ungrouped_cols)
+{
+ if (THRhighwater()) {
+ (void) sql_error(query->sql, 10, SQLSTATE(42000) "Query too
complex: running out of stack space");
+ return ;
}
if (is_basetable(rel->op)) {
- return 0;
+ return ;
} else if (is_base(rel->op)) {
- return exps_only_freevar(query, rel->exps, found_one,
found_aggr) && (!rel->r || (rel->r && rel_only_freevar(query, rel->r,
found_one, found_aggr)));
+ exps_only_freevar(query, rel->exps, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ if (rel->r)
+ rel_only_freevar(query, rel->r, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
} else if (is_simple_project(rel->op) || is_groupby(rel->op) ||
is_select(rel->op) || is_topn(rel->op) || is_sample(rel->op)) {
- if ((is_simple_project(rel->op) || is_groupby(rel->op)) &&
(rel->r && !exps_only_freevar(query, rel->r, found_one, found_aggr)))
- return 0;
- return exps_only_freevar(query, rel->exps, found_one,
found_aggr) && (!rel->l || (rel->l && rel_only_freevar(query, rel->l,
found_one, found_aggr)));
+ if ((is_simple_project(rel->op) || is_groupby(rel->op)) &&
rel->r)
+ exps_only_freevar(query, rel->r, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ exps_only_freevar(query, rel->exps, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ if (rel->l)
+ rel_only_freevar(query, rel->l, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
} else if (is_join(rel->op) || is_set(rel->op) || is_semi(rel->op) ||
is_modify(rel->op)) {
- return exps_only_freevar(query, rel->exps, found_one,
found_aggr) && rel_only_freevar(query, rel->l, found_one, found_aggr) &&
rel_only_freevar(query, rel->r, found_one, found_aggr);
+ exps_only_freevar(query, rel->exps, all_freevar,
found_one_freevar, found_aggr, ungrouped_cols);
+ rel_only_freevar(query, rel->l, all_freevar, found_one_freevar,
found_aggr, ungrouped_cols);
+ rel_only_freevar(query, rel->r, all_freevar, found_one_freevar,
found_aggr, ungrouped_cols);
}
- return 0;
+ return ;
}
static int
diff --git a/sql/server/rel_unnest.h b/sql/server/rel_unnest.h
--- a/sql/server/rel_unnest.h
+++ b/sql/server/rel_unnest.h
@@ -17,7 +17,7 @@ extern int exp_has_freevar(mvc *sql, sql
extern int exps_have_freevar(mvc *sql, list *exps);
extern int rel_has_freevar(mvc *sql, sql_rel *r);
-extern int exp_only_freevar(sql_query *query, sql_exp *e, bool *found_one,
bool *found_aggr);
+extern void exp_only_freevar(sql_query *query, sql_exp *e, unsigned int
*all_freevar, bool *found_one_freevar, bool *found_aggr, list **ungrouped_cols);
extern sql_rel *rel_unnest(mvc *sql, sql_rel *rel);
extern void exps_set_freevar(mvc *sql, list *exps, sql_rel *r);
diff --git a/sql/test/Tests/hot-snapshot.py b/sql/test/Tests/hot-snapshot.py
--- a/sql/test/Tests/hot-snapshot.py
+++ b/sql/test/Tests/hot-snapshot.py
@@ -108,6 +108,10 @@ def main():
# uncommitted1 and uncommitted2 should not be present
assert foo == [('committed1',)]
+ cur3.close()
+ conn3.close()
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list