Changeset: 9a20823adaa8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9a20823adaa8
Modified Files:
sql/server/rel_propagate.c
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/server/rel_updates.c
sql/test/subquery/Tests/subquery3.stable.err
sql/test/subquery/Tests/subquery3.stable.out
sql/test/subquery/Tests/subquery5.stable.err
sql/test/subquery/Tests/subquery5.stable.out
Branch: Jun2020
Log Message:
small fixes for UNION, INTERSECT, EXCEPT in project/subqueries
handling values with correlation earlier
diffs (263 lines):
diff --git a/sql/server/rel_propagate.c b/sql/server/rel_propagate.c
--- a/sql/server/rel_propagate.c
+++ b/sql/server/rel_propagate.c
@@ -81,7 +81,7 @@ rel_generate_anti_insert_expression(mvc
*anti_rel = rel_project(sql->sa, *anti_rel, l);
inserts = (*anti_rel)->l;
- if (inserts->op != op_project && inserts->op != op_basetable &&
inserts->op != op_table)
+ if (inserts->op != op_project && inserts->op != op_union &&
inserts->op != op_basetable && inserts->op != op_table)
inserts = inserts->l;
for (node *n = t->columns.set->h, *m = inserts->exps->h; n &&
m; n = n->next, m = m->next) {
sql_column *col = n->data;
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
@@ -1759,7 +1759,7 @@ rel_compare_exp_(sql_query *query, sql_r
else
return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000)
"SELECT: cannot use non GROUP BY column in query results without an aggregate
function");
}
- if (rs->card <= CARD_ATOM && (exp_is_atom(rs) || exp_has_freevar(sql,
rs)) &&
+ if (rs->card <= CARD_ATOM && (exp_is_atom(rs) || exp_has_freevar(sql,
rs) || exp_has_freevar(sql, ls)) &&
(!rs2 || (rs2->card <= CARD_ATOM && (exp_is_atom(rs2) ||
exp_has_freevar(sql, rs2))))) {
if ((ls->card == rs->card && !rs2) || rel->processed) /* bin
compare op */
return rel_select(sql->sa, rel, e);
@@ -1886,7 +1886,7 @@ rel_compare(sql_query *query, sql_rel *r
ls = rel_value_exp(query, &rel, lo, f, ek);
if (!ls)
return NULL;
- if (ls && rel && exp_has_freevar(sql, ls) && (is_sql_sel(f) ||
is_sql_having(f)))
+ if (ls && rel && exp_has_freevar(sql, ls) && is_sql_sel(f))
ls = rel_project_add_exp(sql, rel, ls);
if (quantifier)
ek.card = card_set;
@@ -2448,7 +2448,7 @@ rel_logical_value_exp(sql_query *query,
return NULL;
if (ek.card <= card_set && is_project(sq->op) &&
list_length(sq->exps) > 1)
return sql_error(sql, 02, SQLSTATE(42000) "SELECT:
subquery must return only one column");
- if (ek.card < card_set && sq->card >= CARD_MULTI &&
(is_sql_sel(f) | is_sql_where(f)) && rel && (!*rel || is_basetable((*rel)->op)
|| is_simple_project((*rel)->op)))
+ if (ek.card < card_set && sq->card >= CARD_MULTI &&
(is_sql_sel(f) | is_sql_having(f) | ( is_sql_where(f) && rel && (!*rel ||
is_basetable((*rel)->op) || is_simple_project((*rel)->op)))))
sq = rel_zero_or_one(sql, sq, ek);
return exp_rel(sql, sq);
}
@@ -3509,7 +3509,10 @@ static sql_exp *
return sql_error(sql, 05, SQLSTATE(42000)
"SELECT: aggregate functions not allowed in functions in FROM");
if (card > CARD_AGGR) { /* used an expression before on
the non grouped relation */
sql_exp *lu = query_outer_last_used(query,
all_freevar-1);
- return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer
query", exp_relname(lu), exp_name(lu));
+ if (lu->type == e_column)
+ return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer
query", (char*)lu->l, (char*)lu->r);
+ else
+ return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer
query", exp_relname(lu), exp_name(lu));
}
if (is_outer(groupby))
return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
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
@@ -2887,6 +2887,42 @@ rewrite_complex(mvc *sql, sql_rel *rel,
return e;
}
+/* rewrite project [ [multi values], [multi values2] , .. [] ] -> union ) */
+static sql_rel *
+rewrite_values(mvc *sql, sql_rel *rel, int *changes)
+{
+ (void)changes;
+ if (!is_simple_project(rel->op) || list_empty(rel->exps))
+ return rel;
+ sql_exp *e = rel->exps->h->data;
+
+ if (!is_values(e) || list_length(exp_get_values(e))<=1 ||
!rel_has_freevar(sql, rel))
+ return rel;
+
+ list *exps = sa_list(sql->sa);
+ sql_rel *cur = NULL;
+ list *vals = exp_get_values(e);
+ for(int i = 0; i<list_length(vals); i++) {
+ sql_rel *nrel = rel_project(sql->sa, NULL, sa_list(sql->sa));
+ for(node *n = rel->exps->h; n; n = n->next) {
+ sql_exp *e = n->data;
+ if (i == 0)
+ append(exps, exp_ref(sql, e));
+ list *vals = exp_get_values(e);
+ sql_exp *v = list_fetch(vals, i);
+ append(nrel->exps, v);
+ rel_set_exps(nrel, nrel->exps);
+ }
+ if (cur) {
+ nrel = rel_setop(sql->sa, cur, nrel, op_union);
+ rel_set_exps(nrel, exps);
+ }
+ cur = nrel;
+ }
+ rel = cur;
+ return rel;
+}
+
sql_rel *
rel_unnest(mvc *sql, sql_rel *rel)
{
@@ -2903,9 +2939,12 @@ rel_unnest(mvc *sql, sql_rel *rel)
rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_rank, &changes);
rel = rel_visitor_bottomup(sql, rel, &rewrite_outer2inner_union,
&changes);
+ // remove empty project/groupby !
+ rel = rel_visitor_bottomup(sql, rel, &rewrite_empty_project, &changes);
rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_complex, &changes);
rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_ifthenelse,
&changes); /* add isnull handling */
+ rel = rel_visitor_bottomup(sql, rel, &rewrite_values, &changes);
rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_exp_rel, &changes);
rel = rel_visitor_bottomup(sql, rel, &rewrite_join2semi, &changes);
/* where possible convert anyequal functions into marks */
rel = rel_visitor_bottomup(sql, rel, &rewrite_compare_exp, &changes);
/* only allow for e_cmp in selects and handling */
@@ -2919,6 +2958,7 @@ rel_unnest(mvc *sql, sql_rel *rel)
rel = rel_visitor_bottomup(sql, rel, &rewrite_remove_xp, &changes);
/* remove crossproducts with project [ atom ] */
rel = rel_visitor_bottomup(sql, rel, &rewrite_groupings, &changes);
/* transform group combinations into union of group relations */
rel = rel_visitor_bottomup(sql, rel, &rewrite_empty_project, &changes);
+ // needed again!
rel = rel_exp_visitor_bottomup(sql, rel, &exp_reset_card, &changes);
return rel;
}
diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -503,14 +503,8 @@ insert_generate_inserts(sql_query *query
sql_exp *ins =
insert_value(query, c, &r, n->data.sym, action);
if (!ins)
return NULL;
- if (r && inner)
- inner =
rel_crossproduct(sql->sa, inner, r, op_join);
- else if (r)
- inner = r;
- if (inner && !exp_name(ins) &&
!exp_is_atom(ins)) {
+ if (!exp_name(ins))
exp_label(sql->sa, ins,
++sql->label);
- ins = exp_ref(sql, ins);
- }
list_append(vals_list, ins);
}
} else {
diff --git a/sql/test/subquery/Tests/subquery3.stable.err
b/sql/test/subquery/Tests/subquery3.stable.err
--- a/sql/test/subquery/Tests/subquery3.stable.err
+++ b/sql/test/subquery/Tests/subquery3.stable.err
@@ -325,14 +325,14 @@ MAPI = (monetdb) /var/tmp/mtest-596453/
QUERY = SELECT
(SELECT i2.i FROM (VALUES (i1.i), (i1.i)) as i2(i))
FROM integers i1; --error, more than one row returned by a subquery
used as an expression
-ERROR = !Cardinality violation, scalar value expected
-CODE = 21000
-MAPI = (monetdb) /var/tmp/mtest-600940/.s.monetdb.32137
+ERROR = !zero_or_one: cardinality violation, scalar expression expected
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-2650031/.s.monetdb.39763
QUERY = SELECT
(SELECT i2.i FROM (VALUES (i1.i, i1.i), (i1.i, i1.i)) as
i2(i,j))
FROM integers i1; --error, more than one row returned by a subquery
used as an expression
-ERROR = !Cardinality violation, scalar value expected
-CODE = 21000
+ERROR = !zero_or_one: cardinality violation, scalar expression expected
+CODE = M0M29
# 17:40:41 >
# 17:40:41 > "Done."
diff --git a/sql/test/subquery/Tests/subquery3.stable.out
b/sql/test/subquery/Tests/subquery3.stable.out
--- a/sql/test/subquery/Tests/subquery3.stable.out
+++ b/sql/test/subquery/Tests/subquery3.stable.out
@@ -36,7 +36,7 @@ stdout of test 'subquery3` in directory
#FROM another_T t1
#GROUP BY t1.col6, t1.col7;
% . # table_name
-% %36 # name
+% %33 # name
% boolean # type
% 5 # length
[ false ]
@@ -63,7 +63,7 @@ stdout of test 'subquery3` in directory
#FROM another_T
#GROUP BY col1, col2, col5;
% ., . # table_name
-% %53, %54 # name
+% %55, %56 # name
% int, int # type
% 1, 1 # length
[ 1, 0 ]
@@ -193,8 +193,8 @@ stdout of test 'subquery3` in directory
# NOT SUM(t1.col2) * MIN(t1.col6 + t1.col6 - t1.col6 * t1.col6) NOT IN
(SELECT MAX(t2.col6) FROM another_T t2 GROUP BY t1.col6 HAVING t1.col7 +
MIN(t2.col8) < MAX(t2.col7 - t1.col6))
#FROM another_T t1
#GROUP BY t1.col7, t1.col6;
-% .%24 # table_name
-% %24 # name
+% .%23 # table_name
+% %23 # name
% boolean # type
% 5 # length
[ false ]
diff --git a/sql/test/subquery/Tests/subquery5.stable.err
b/sql/test/subquery/Tests/subquery5.stable.err
--- a/sql/test/subquery/Tests/subquery5.stable.err
+++ b/sql/test/subquery/Tests/subquery5.stable.err
@@ -116,9 +116,9 @@ ERROR = !SELECT: subquery must return on
CODE = 42000
MAPI = (monetdb) /var/tmp/mtest-577635/.s.monetdb.34590
QUERY = SELECT (VALUES(col1), (col2)) FROM another_t; --error, more than one
row returned by a subquery used as an expression
-ERROR = !Cardinality violation, scalar value expected
-CODE = 21000
-MAPI = (monetdb) /var/tmp/mtest-146231/.s.monetdb.30793
+ERROR = !zero_or_one: cardinality violation, scalar expression expected
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-2671726/.s.monetdb.31336
QUERY = SELECT integers.i FROM (VALUES(4),(5),(6),(8)) AS integers(i),
integers; --error table integers specified more than once
ERROR = !SELECT: relation name "integers" specified more than once
CODE = 42000
@@ -170,6 +170,18 @@ MAPI = (monetdb) /var/tmp/mtest-1772822
QUERY = SELECT CORR((SELECT i1.i FROM integers i2), (SELECT SUM(i1.i + i2.i)
FROM integers i2)) FROM integers i1;
ERROR = !zero_or_one: cardinality violation, scalar expression expected
CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-2671726/.s.monetdb.31336
+QUERY = SELECT (VALUES(SUM(i1.i)) UNION VALUES(AVG(i1.i))) FROM integers i1;
+ERROR = !zero_or_one: cardinality violation, scalar expression expected
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-2671726/.s.monetdb.31336
+QUERY = SELECT ((SELECT SUM(i1.i)) UNION ALL (SELECT AVG(i1.i))) FROM integers
i1;
+ERROR = !zero_or_one: cardinality violation, scalar expression expected
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-2671726/.s.monetdb.31336
+QUERY = SELECT ((SELECT i1.i NOT IN (SELECT i1.i)) UNION (SELECT SUM(i1.i) IN
(SELECT i1.i))) FROM integers i1;
+ERROR = !SELECT: subquery uses ungrouped column "i1.i" from outer query
+CODE = 42000
# 08:41:39 >
# 08:41:39 > "Done."
diff --git a/sql/test/subquery/Tests/subquery5.stable.out
b/sql/test/subquery/Tests/subquery5.stable.out
--- a/sql/test/subquery/Tests/subquery5.stable.out
+++ b/sql/test/subquery/Tests/subquery5.stable.out
@@ -281,6 +281,29 @@ stdout of test 'subquery5` in directory
% 5 # length
[ true ]
[ true ]
+#SELECT (VALUES (SUM(i1.i)),(AVG(i1.i)) INTERSECT VALUES(AVG(i1.i))) FROM
integers i1;
+% .%17 # table_name
+% %17 # name
+% double # type
+% 24 # length
+[ 2 ]
+#SELECT SUM(i1.i) FROM integers i1 HAVING (VALUES(SUM(i1.i)),(AVG(i1.i))
INTERSECT VALUES(AVG(i1.i))) > 0;
+% .%1 # table_name
+% %1 # name
+% hugeint # type
+% 1 # length
+[ 6 ]
+#SELECT MAX(i1.i) FROM integers i1 HAVING (VALUES((AVG(i1.i))) EXCEPT
VALUES(AVG(i1.i))) <> 0;
+% .%1 # table_name
+% %1 # name
+% int # type
+% 1 # length
+#SELECT (SELECT 6 EXCEPT (SELECT SUM(i1.i))) IN (SELECT 1) FROM integers i1;
-- OPTmergetableImplementation: !ERROR: Mergetable bailout on group input reuse
in group statement
+% .%24 # table_name
+% %24 # name
+% boolean # type
+% 5 # length
+[ NULL ]
#DROP FUNCTION evilfunction(INT);
#DROP TABLE tbl_ProductSales;
#DROP TABLE another_T;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list