Changeset: 3e37f91aafc7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3e37f91aafc7
Modified Files:
sql/server/rel_rel.c
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/test/subquery/Tests/subquery3.stable.out
Branch: default
Log Message:
correctly set the cardinality of set relational operators
properly propagate the has_nil into the aggregators
limit the projection list inside a general unnest to expressions not
in the ad list (ie no freevars)
diffs (229 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
@@ -441,7 +441,11 @@ rel_setop(sql_allocator *sa, sql_rel *l,
rel->r = r;
rel->op = setop;
rel->exps = NULL;
- rel->card = CARD_MULTI;
+ if (setop == op_union) {
+ rel->card = CARD_MULTI;
+ } else {
+ rel->card = l->card;
+ }
if (l && r)
rel->nrcols = l->nrcols + r->nrcols;
return rel;
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
@@ -536,7 +536,7 @@ find_table_function_type(mvc *sql, sql_s
if (e->card > CARD_ATOM) {
sql_subaggr *zero_or_one =
sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(e));
- e = exp_aggr1(sql->sa, e, zero_or_one,
0, 0, CARD_ATOM, 0);
+ e = exp_aggr1(sql->sa, e, zero_or_one,
0, 0, CARD_ATOM, has_nil(e));
}
append(nexps, e);
}
@@ -1845,7 +1845,7 @@ static sql_exp*
if (table_func && e->card > CARD_ATOM) {
sql_subaggr *zero_or_one =
sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(e));
- e = exp_aggr1(sql->sa, e, zero_or_one,
0, 0, CARD_ATOM, 0);
+ e = exp_aggr1(sql->sa, e, zero_or_one,
0, 0, CARD_ATOM, has_nil(e));
}
append(nexps, e);
}
@@ -2690,7 +2690,7 @@ rel_unop_(mvc *sql, sql_rel *rel, sql_ex
if (card == card_relation && e->card > CARD_ATOM) {
sql_subaggr *zero_or_one = sql_bind_aggr(sql->sa,
sql->session->schema, "zero_or_one", exp_subtype(e));
- e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM,
0);
+ e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM,
has_nil(e));
}
return exp_unop(sql->sa, e, f);
} else if (e) {
@@ -2860,12 +2860,12 @@ rel_binop_(mvc *sql, sql_rel *rel, sql_e
if (card == card_relation && l->card > CARD_ATOM) {
sql_subaggr *zero_or_one = sql_bind_aggr(sql->sa,
sql->session->schema, "zero_or_one", exp_subtype(l));
- l = exp_aggr1(sql->sa, l, zero_or_one, 0, 0, CARD_ATOM,
0);
+ l = exp_aggr1(sql->sa, l, zero_or_one, 0, 0, CARD_ATOM,
has_nil(l));
}
if (card == card_relation && r->card > CARD_ATOM) {
sql_subaggr *zero_or_one = sql_bind_aggr(sql->sa,
sql->session->schema, "zero_or_one", exp_subtype(r));
- r = exp_aggr1(sql->sa, r, zero_or_one, 0, 0, CARD_ATOM,
0);
+ r = exp_aggr1(sql->sa, r, zero_or_one, 0, 0, CARD_ATOM,
has_nil(r));
}
/* bind types of l and r */
t1 = exp_subtype(l);
@@ -4661,7 +4661,7 @@ rel_value_exp2(sql_query *query, sql_rel
sql_subaggr *zero_or_one =
sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(e));
e = exp_ref(sql->sa, e);
- e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0,
CARD_ATOM, 0);
+ e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0,
CARD_ATOM, has_nil(e));
r = rel_groupby(sql, r, NULL);
(void)rel_groupby_add_aggr(sql, r, e);
}
@@ -4886,7 +4886,7 @@ rel_having_limits_nodes(sql_query *query
if ((ek.card != card_relation && sn->limit) &&
(ek.card == card_value && sn->limit)) {
sql_subaggr *zero_or_one =
sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(l));
- l = exp_aggr1(sql->sa, l, zero_or_one, 0, 0,
CARD_ATOM, 0);
+ l = exp_aggr1(sql->sa, l, zero_or_one, 0, 0,
CARD_ATOM, has_nil(l));
}
append(exps, l);
} else
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
@@ -601,7 +601,7 @@ rel_general_unnest(mvc *sql, sql_rel *re
node *n, *m;
int nr;
- sql_rel *l = rel->l, *r = rel->r;
+ sql_rel *l = rel->l, *r = rel->r, *inner_r;
/* rewrite T1 dependent join T2 -> T1 join D dependent join T2,
where the T1/D join adds (equality) predicates (for the Domain (ad)) and D is
are the distinct(projected(ad) from T1) */
sql_rel *D = rel_project(sql->sa, rel_dup(l), exps_copy(sql,
ad));
set_distinct(D);
@@ -610,7 +610,26 @@ rel_general_unnest(mvc *sql, sql_rel *re
r->op = /*is_semi(rel->op)?op_left:*/op_join;
move_join_exps(sql, rel, r);
set_dependent(r);
- r = rel_project(sql->sa, r,
(is_semi(r->op))?sa_list(sql->sa):rel_projections(sql, r->r, NULL, 1, 1));
+ inner_r = r;
+ r = rel_project(sql->sa, r,
(is_semi(inner_r->op))?sa_list(sql->sa):rel_projections(sql, r->r, NULL, 1, 1));
+
+ if (!is_semi(inner_r->op)) { /* skip the free vars */
+ list *exps = sa_list(sql->sa);
+
+ for(node *n=r->exps->h; n; n = n->next) {
+ sql_exp *e = n->data, *ne = NULL;
+
+ if (e->l) {
+ ne = exps_bind_column2(ad, e->l, e->r );
+ } else {
+ ne = exps_bind_column(ad, e->r, NULL);
+ }
+ if (!ne)
+ append(exps,e);
+ }
+ r->exps = exps;
+ }
+
/* append ad + rename */
nr = sql->label+1;
sql->label += list_length(ad);
@@ -1897,7 +1916,7 @@ rewrite_anyequal(mvc *sql, sql_rel *rel,
lsq->exps = exps;
sql_subaggr *ea = sql_bind_aggr(sql->sa,
sql->session->schema, is_anyequal(sf)?"anyequal":"allnotequal",
exp_subtype(re));
- sql_exp *a = exp_aggr1(sql->sa, le, ea, 0, 0,
CARD_AGGR, 0);
+ sql_exp *a = exp_aggr1(sql->sa, le, ea, 0, 0,
CARD_AGGR, has_nil(le));
append(a->l, re);
append(a->l, rid);
le = rel_groupby_add_aggr(sql, lsq, a);
@@ -2059,14 +2078,14 @@ rewrite_compare(mvc *sql, sql_rel *rel,
a = sql_bind_aggr(sql->sa,
sql->session->schema, "all", exp_subtype(re));
is_cnt = 1;
}
- re = exp_aggr1(sql->sa, re, a, 0, 1,
CARD_AGGR, 0);
+ re = exp_aggr1(sql->sa, re, a, 0, 1,
CARD_AGGR, has_nil(re));
re = rel_groupby_add_aggr(sql, rsq, re);
} else if (rsq && exp_card(re) > CARD_ATOM) {
sql_subaggr *zero_or_one =
sql_bind_aggr(sql->sa, NULL, compare_aggr_op(op, quantifier), exp_subtype(re));
rsq = rel_groupby(sql, rsq, NULL);
- re = exp_aggr1(sql->sa, re,
zero_or_one, 0, 0, CARD_AGGR, 0);
+ re = exp_aggr1(sql->sa, re,
zero_or_one, 0, 0, CARD_AGGR, has_nil(re));
re = rel_groupby_add_aggr(sql, rsq, re);
}
if (rsq)
@@ -2272,7 +2291,7 @@ rewrite_exists(mvc *sql, sql_rel *rel, s
if (exp_is_rel(ie)) /* TODO add set rel function */
ie->l = sq;
ea = sql_bind_aggr(sql->sa, sql->session->schema,
is_exists(sf)?"exist":"not_exist", exp_subtype(le));
- le = exp_aggr1(sql->sa, le, ea, 0, 0, CARD_AGGR, 0);
+ le = exp_aggr1(sql->sa, le, ea, 0, 0, CARD_AGGR,
has_nil(le));
le = rel_groupby_add_aggr(sql, sq, le);
if (rel_has_freevar(sql, sq))
ne = le;
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
@@ -249,6 +249,71 @@ stdout of test 'subquery3` in directory
[ 1 ]
[ 1 ]
[ 1 ]
+#SELECT
+# 1
+#FROM another_T t1
+#GROUP BY t1.col1, t1.col2, t1.col4
+#HAVING (t1.col1 = ANY (SELECT MAX(ColID + col2) FROM tbl_ProductSales)) <
+# ((SELECT NOT EXISTS (SELECT t1.col2 FROM tbl_ProductSales WHERE
tbl_ProductSales.ColID = t1.col1)) INTERSECT
+# (SELECT NOT t1.col1 IN (SELECT MAX(t1.col7) EXCEPT SELECT tp.ColID FROM
tbl_ProductSales tp)));
+% . # table_name
+% single_value # name
+% tinyint # type
+% 1 # length
+[ 1 ]
+[ 1 ]
+[ 1 ]
+#SELECT
+# col6,
+# col7,
+# NOT SUM(t1.col6) NOT IN (SELECT MAX(t2.col6) FROM another_T t2 GROUP BY
t1.col6 HAVING t1.col7 < MAX(t1.col6))
+#FROM another_T t1
+#GROUP BY t1.col7, t1.col6;
+% .t1, .t1, .%15 # table_name
+% col6, col7, %15 # name
+% int, int, boolean # type
+% 4, 4, 5 # length
+[ 6, 7, false ]
+[ 66, 77, false ]
+[ 666, 777, false ]
+[ 6666, 7777, false ]
+#SELECT
+# col6,
+# col7,
+# NOT SUM(t1.col6) NOT IN (SELECT MAX(t2.col6) FROM another_T t2 GROUP BY
t1.col6 HAVING t1.col7 < MAX(t2.col7 - t1.col6))
+#FROM another_T t1
+#GROUP BY t1.col7, t1.col6;
+% .t1, .t1, .%15 # table_name
+% col6, col7, %15 # name
+% int, int, boolean # type
+% 4, 4, 5 # length
+[ 6, 7, false ]
+[ 66, 77, false ]
+[ 666, 777, false ]
+[ 6666, 7777, false ]
+#SELECT
+# CASE WHEN NULL IN (SELECT MIN(ColID) FROM tbl_ProductSales tp LEFT JOIN
another_T t2 ON tp.ColID = t1.col1) THEN 1 ELSE 2 END
+#FROM another_T t1
+#GROUP BY t1.col1, t1.col2;
+% .%32 # table_name
+% %32 # name
+% tinyint # type
+% 1 # length
+[ 2 ]
+[ 2 ]
+[ 2 ]
+[ 2 ]
+#SELECT
+# CASE WHEN NULL NOT IN (SELECT 1 FROM tbl_ProductSales tp FULL OUTER JOIN
another_T t2 ON tp.ColID = t1.col1) THEN 1 ELSE 2 END
+#FROM another_T t1;
+% .%34 # table_name
+% %34 # name
+% tinyint # type
+% 1 # length
+[ 2 ]
+[ 2 ]
+[ 2 ]
+[ 2 ]
#DROP TABLE tbl_ProductSales;
#DROP TABLE another_T;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list