Changeset: 0aa4c19a7eb6 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/0aa4c19a7eb6 Modified Files: sql/server/rel_optimizer.c sql/test/SQLancer/Tests/sqlancer16.test Branch: Jul2021 Log Message:
Be more defensive with potential self references created by rel_push_func_down optimizer diffs (169 lines): 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 @@ -1432,22 +1432,22 @@ exps_need_push_down( list *exps ) return 0; } -static sql_exp *exp_push_single_func_down(visitor *v, sql_rel *rel, sql_exp *e, int depth); +static sql_exp *exp_push_single_func_down(visitor *v, sql_rel *rel, sql_rel *ol, sql_rel *or, sql_exp *e, int depth); static list * -exps_push_single_func_down(visitor *v, sql_rel *rel, list *exps, int depth) +exps_push_single_func_down(visitor *v, sql_rel *rel, sql_rel *ol, sql_rel *or, list *exps, int depth) { if (mvc_highwater(v->sql)) return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space"); for (node *n = exps->h; n; n = n->next) - if ((n->data = exp_push_single_func_down(v, rel, n->data, depth)) == NULL) + if ((n->data = exp_push_single_func_down(v, rel, ol, or, n->data, depth)) == NULL) return NULL; return exps; } static sql_exp * -exp_push_single_func_down(visitor *v, sql_rel *rel, sql_exp *e, int depth) +exp_push_single_func_down(visitor *v, sql_rel *rel, sql_rel *ol, sql_rel *or, sql_exp *e, int depth) { if (mvc_highwater(v->sql)) return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space"); @@ -1455,26 +1455,26 @@ exp_push_single_func_down(visitor *v, sq switch(e->type) { case e_cmp: { if (e->flag == cmp_or || e->flag == cmp_filter) { - if ((e->l = exps_push_single_func_down(v, rel, e->l, depth + 1)) == NULL) + if ((e->l = exps_push_single_func_down(v, rel, ol, or, e->l, depth + 1)) == NULL) return NULL; - if ((e->r = exps_push_single_func_down(v, rel, e->r, depth + 1)) == NULL) + if ((e->r = exps_push_single_func_down(v, rel, ol, or, e->r, depth + 1)) == NULL) return NULL; } else if (e->flag == cmp_in || e->flag == cmp_notin) { - if ((e->l = exp_push_single_func_down(v, rel, e->l, depth + 1)) == NULL) + if ((e->l = exp_push_single_func_down(v, rel, ol, or, e->l, depth + 1)) == NULL) return NULL; - if ((e->r = exps_push_single_func_down(v, rel, e->r, depth + 1)) == NULL) + if ((e->r = exps_push_single_func_down(v, rel, ol, or, e->r, depth + 1)) == NULL) return NULL; } else { - if ((e->l = exp_push_single_func_down(v, rel, e->l, depth + 1)) == NULL) + if ((e->l = exp_push_single_func_down(v, rel, ol, or, e->l, depth + 1)) == NULL) return NULL; - if ((e->r = exp_push_single_func_down(v, rel, e->r, depth + 1)) == NULL) + if ((e->r = exp_push_single_func_down(v, rel, ol, or, e->r, depth + 1)) == NULL) return NULL; - if (e->f && (e->f = exp_push_single_func_down(v, rel, e->f, depth + 1)) == NULL) + if (e->f && (e->f = exp_push_single_func_down(v, rel, ol, or, e->f, depth + 1)) == NULL) return NULL; } } break; case e_convert: - if ((e->l = exp_push_single_func_down(v, rel, e->l, depth + 1)) == NULL) + if ((e->l = exp_push_single_func_down(v, rel, ol, or, e->l, depth + 1)) == NULL) return NULL; break; case e_aggr: @@ -1491,11 +1491,11 @@ exp_push_single_func_down(visitor *v, sq exp_label(v->sql->sa, e, ++v->sql->label); /* we need a full projection, group by's and unions cannot be extended with more expressions */ if (mustr) { - if (!is_simple_project(r->op) || !list_empty(r->r) || !r->l) + if (r == or) /* don't project twice */ rel->r = r = rel_project(v->sql->sa, r, rel_projections(v->sql, r, NULL, 1, 1)); list_append(r->exps, e); } else { - if (!is_simple_project(l->op) || !list_empty(l->r) || !l->l) + if (l == ol) /* don't project twice */ rel->l = l = rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1)); list_append(l->exps, e); } @@ -1504,7 +1504,7 @@ exp_push_single_func_down(visitor *v, sq } } break; case e_atom: { - if (e->f && (e->f = exps_push_single_func_down(v, rel, e->f, depth + 1)) == NULL) + if (e->f && (e->f = exps_push_single_func_down(v, rel, ol, or, e->f, depth + 1)) == NULL) return NULL; } break; case e_column: @@ -1524,7 +1524,7 @@ rel_push_func_down(visitor *v, sql_rel * /* only push down when is useful */ if ((is_select(rel->op) && list_length(rel->exps) <= 1) || rel_is_ref(l) || (is_joinop(rel->op) && rel_is_ref(r))) return rel; - if (exps_can_push_func(rel->exps, rel) && exps_need_push_down(rel->exps) && !exps_push_single_func_down(v, rel, rel->exps, 0)) + if (exps_can_push_func(rel->exps, rel) && exps_need_push_down(rel->exps) && !exps_push_single_func_down(v, rel, l, r, rel->exps, 0)) return NULL; if (v->changes > changes) /* once we get a better join order, we can try to remove this projection */ return rel_project(v->sql->sa, rel, rel_projections(v->sql, rel, NULL, 1, 1)); @@ -1533,7 +1533,7 @@ rel_push_func_down(visitor *v, sql_rel * sql_rel *pl = rel->l; if (is_joinop(pl->op) && exps_can_push_func(rel->exps, rel)) { - sql_rel *l = pl->l, *r = pl->r; + sql_rel *l = pl->l, *r = pl->r, *ol = l, *or = r; for (node *n = rel->exps->h; n; ) { node *next = n->next; @@ -1542,13 +1542,13 @@ rel_push_func_down(visitor *v, sql_rel * if ((can_push_func(e, l, &mustl, 0) && mustl) || (can_push_func(e, r, &mustr, 0) && mustr)) { if (mustl) { - if (!is_simple_project(l->op) || !list_empty(l->r) || !l->l) + if (l == ol) /* don't project twice */ pl->l = l = rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1)); list_append(l->exps, e); list_remove_node(rel->exps, NULL, n); v->changes++; } else { - if (!is_simple_project(r->op) || !list_empty(r->r) || !r->l) + if (r == or) /* don't project twice */ pl->r = r = rel_project(v->sql->sa, r, rel_projections(v->sql, r, NULL, 1, 1)); list_append(r->exps, e); list_remove_node(rel->exps, NULL, n); diff --git a/sql/test/SQLancer/Tests/sqlancer16.test b/sql/test/SQLancer/Tests/sqlancer16.test --- a/sql/test/SQLancer/Tests/sqlancer16.test +++ b/sql/test/SQLancer/Tests/sqlancer16.test @@ -55,6 +55,43 @@ statement ok START TRANSACTION statement ok +CREATE TABLE "t1" ("c0" INTEGER) + +statement ok rowcount 4 +INSERT INTO "t1" VALUES (1), (2), (3), (4) + +query I rowsort +SELECT 1 FROM t1 FULL OUTER JOIN (SELECT 2 FROM t1 JOIN (SELECT sql_min(TIME '01:00:00', TIME '12:05:37') FROM t1) AS sub0(c0) ON TRUE WHERE true) AS sub0(c0) +ON CAST(6 AS DOUBLE)/(CASE 3 WHEN sub0.c0 THEN 0.2 END) > 2 +---- +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 + +statement ok +ROLLBACK + +statement ok +START TRANSACTION + +statement ok CREATE TABLE t0(c0 INTERVAL DAY PRIMARY KEY, c1 BIGINT) statement ok _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list