Changeset: 2058190fb1d3 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/2058190fb1d3 Modified Files: sql/server/rel_exp.c sql/server/rel_exp.h sql/server/rel_optimizer.c sql/server/rel_unnest.c sql/test/SQLancer/Tests/sqlancer23.test sql/test/astro/Tests/astro.test Branch: default Log Message:
push up select expressions with freevars first added some missing binding attempts diffs (truncated from 477 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 @@ -3404,3 +3404,17 @@ rel_set_type_recurse(mvc *sql, sql_subty } return 0; } + +sql_exp * +list_find_exp( list *exps, sql_exp *e) +{ + sql_exp *ne = NULL; + + if (e->type != e_column) + return NULL; + if (( e->l && (ne=exps_bind_column2(exps, e->l, e->r, NULL)) != NULL) || + ((!e->l && (ne=exps_bind_column(exps, e->r, NULL, NULL, 1)) != NULL))) + return ne; + return NULL; +} + 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 @@ -186,6 +186,7 @@ extern sql_rel *find_one_rel(list *rels, extern sql_exp *exps_bind_column(list *exps, const char *cname, int *ambiguous, int *multiple, int no_tname /* set if expressions should be without a tname */); extern sql_exp *exps_bind_column2(list *exps, const char *rname, const char *cname, int *multiple); extern sql_exp *exps_bind_alias(list *exps, const char *rname, const char *cname); +extern sql_exp * list_find_exp( list *exps, sql_exp *e); extern unsigned int exps_card( list *l ); extern void exps_fix_card( list *exps, unsigned int card); 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 @@ -52,19 +52,6 @@ sjexp_col(sql_exp *e, sql_rel *r) return res; } -static sql_exp * -list_find_exp( list *exps, sql_exp *e) -{ - sql_exp *ne = NULL; - - if (e->type != e_column) - return NULL; - if (( e->l && (ne=exps_bind_column2(exps, e->l, e->r, NULL)) != NULL) || - ((!e->l && (ne=exps_bind_column(exps, e->r, NULL, NULL, 1)) != NULL))) - return ne; - return NULL; -} - static int kc_column_cmp(sql_kc *kc, sql_column *c) { 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 @@ -503,6 +503,15 @@ rel_bind_var(mvc *sql, sql_rel *rel, sql } } +static void +rel_bind_vars(mvc *sql, sql_rel *rel, list *exps) +{ + if (list_empty(exps)) + return; + for(node *n=exps->h; n; n = n->next) + rel_bind_var(sql, rel, n->data); +} + static sql_exp * push_up_project_exp(mvc *sql, sql_rel *rel, sql_exp *e); static list * @@ -700,7 +709,7 @@ rel_bound_exp(mvc *sql, sql_rel *rel ) if (exp_is_atom(e)) return e; - if (!is_freevar(e)) + if (!exp_has_freevar(sql, e)) return exp_ref(sql, e); } } @@ -859,7 +868,7 @@ push_up_project(mvc *sql, sql_rel *rel, break; } - if (l && (is_select(l->op) || l->op == op_join || is_semi(l->op)) && !rel_is_ref(l)) { + if (l && (is_select(l->op) || l->op == op_join || is_semi(l->op)) && !rel_is_ref(l) && list_empty(r->attr)) { if (!list_empty(r->exps)) { for(n=r->exps->h; n; n=n->next) { sql_exp *e = n->data; @@ -924,11 +933,6 @@ push_up_project(mvc *sql, sql_rel *rel, sql_rel *n = rel_project( sql->sa, (r->l)?rel:rel->l, rel_projections(sql, rel->l, NULL, 1, 1)); - /* only pass bound variables */ - if (list_empty(rel->attr) && is_left(rel->op) && exps_have_freevar(sql, r->exps)) { - id = rel_bound_exp(sql, r); - id = rel_project_add_exp(sql, n, id); - } if (is_left(rel->op) && !list_empty(rel->attr)) { rel_project_add_exp(sql, n, exp_ref(sql, rel->attr->h->data)); } @@ -937,11 +941,17 @@ push_up_project(mvc *sql, sql_rel *rel, sql_exp *e = m->data; if (!is_freevar(e) || exp_name(e)) { /* only skip full freevars */ - if (exp_has_freevar(sql, e)) { + if (exp_has_freevar(sql, e) || is_atom(e->type)) { rel_bind_var(sql, rel->l, e); if (is_left(rel->op)) { /* add ifthenelse */ - /* need bound var from r */ /* if id is NULL then NULL else e */ + if (!id) { + sql_rel *l = r->l; + if (is_join(l->op)) + id = rel_bound_exp(sql, r); + else + r->l = rel_add_identity(sql, r->l, &id); + } sql_exp *ne = rel_unop_(sql, NULL, exp_copy(sql, id), "sys", "isnull", card_value); set_has_no_nil(ne); ne = rel_nop_(sql, NULL, ne, exp_null(sql->sa, exp_subtype(e)), e, NULL, "sys", "ifthenelse", card_value); @@ -983,6 +993,7 @@ push_up_project(mvc *sql, sql_rel *rel, /* merge project expressions into the join expressions */ rel->exps = push_up_project_exps(sql, r, rel->exps); + rel_bind_vars(sql, rel, rel->exps); if (r && r->op == op_project && r->l) { /* remove old project */ @@ -1396,6 +1407,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis list_hash_clear(nl->exps); n->attr = attr; set_processed(n); + rel_bind_vars(sql, n, n->exps); return n; } @@ -1412,6 +1424,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis if (is_semi(rel->op)) rel->op = op_left; move_join_exps(sql, j, rel); + rel_bind_vars(sql, j, j->exps); return j; } if (!ld) { @@ -1427,6 +1440,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis if (is_semi(rel->op)) rel->op = op_left; move_join_exps(sql, j, rel); + rel_bind_vars(sql, j, j->exps); return j; } assert(0); @@ -1440,6 +1454,7 @@ static sql_rel * push_up_set(mvc *sql, sql_rel *rel, list *ad) { if (rel && (is_join(rel->op) || is_semi(rel->op)) && is_dependent(rel)) { + int single = is_single(rel); sql_rel *d = rel->l, *s = rel->r; /* left of rel should be a set */ @@ -1454,6 +1469,25 @@ push_up_set(mvc *sql, sql_rel *rel, list for (node *n = sr->exps->h, *m = s->exps->h; n && m; n = n->next, m = m->next) exp_prop_alias(sql->sa, n->data, m->data); list_hash_clear(sr->exps); + + int llen = list_length(sl->exps), rlen = list_length(sr->exps), l = 0; + + if (llen != rlen) { + if (llen < rlen) { + list *nr = sa_list(sql->sa); + for(node *n = sr->exps->h ; n && l < llen; n=n->next, l++) + append(nr, n->data); + sr->exps = nr; + sr->nrcols = list_length(nr); + } else { + list *nl = sa_list(sql->sa); + for(node *n = sl->exps->h; n && l < rlen; n=n->next, l++) + append(nl, n->data); + sl->exps = nl; + sl->nrcols = list_length(nl); + } + } + /* D djoin (sl setop sr) -> (D djoin sl) setop (D djoin sr) */ sl = rel_crossproduct(sql->sa, rel_dup(d), sl, rel->op); sl->exps = exps_copy(sql, rel->exps); @@ -1466,7 +1500,7 @@ push_up_set(mvc *sql, sql_rel *rel, list ns = rel_setop(sql->sa, sl, sr, s->op); ns->exps = exps_copy(sql, s->exps); set_processed(ns); - if (is_single(s)) + if (single || is_single(s)) set_single(ns); if (need_distinct(s)) set_distinct(ns); @@ -1485,6 +1519,10 @@ push_up_set(mvc *sql, sql_rel *rel, list ns->r = rel_project(sql->sa, ns->r, rel_projections(sql, ns->r, NULL, 1, 1)); if (is_semi(rel->op)) ns->exps = rel_projections(sql, ns->r, NULL, 1, 1); + if (rel->op == op_anti && s->op == op_union) + ns->op = op_inter; + if (rel->op == op_anti && s->op == op_inter) + ns->op = op_union; rel_destroy(rel); return ns; } @@ -1685,9 +1723,169 @@ rel_unnest_dependent(mvc *sql, sql_rel * return nrel; } +static list * add_missing_project_exps(mvc *sql, sql_rel *rel, list *exps); + +static sql_exp * +add_missing_project_exp(mvc *sql, sql_rel *rel, sql_exp *e) +{ + if (is_freevar(e)) + return e; + if (is_convert(e->type)) { + e->l = add_missing_project_exp(sql, rel, e->l); + } else if (is_compare(e->type)) { + if (e->flag == cmp_in || e->flag == cmp_notin) { + e->l = add_missing_project_exp(sql, rel, e->l); + e->r = add_missing_project_exps(sql, rel, e->r); + } else if (e->flag == cmp_or || e->flag == cmp_filter) { + e->l = add_missing_project_exps(sql, rel, e->l); + e->r = add_missing_project_exps(sql, rel, e->r); + } else { + e->l = add_missing_project_exp(sql, rel, e->l); + e->r = add_missing_project_exp(sql, rel, e->r); + if (e->f) + e->f = add_missing_project_exp(sql, rel, e->f); + } + } else if (is_atom(e->type)) { + if (is_values(e)) + e->f = add_missing_project_exps(sql, rel, e->f); + return e; + } + else if (!list_find_exp(rel->exps, e)) { + exp_label(sql->sa, e, ++sql->label); + append(rel->exps, e); + return exp_ref(sql, e); + } + return e; +} + +static list * +add_missing_project_exps(mvc *sql, sql_rel *rel, list *exps) +{ + if (list_empty(exps)) + return exps; + for(node *n = exps->h; n; n = n->next) + n->data = add_missing_project_exp(sql, rel, n->data); + return exps; +} + +static sql_rel * +push_up_select2(visitor *v, sql_rel *rel) +{ + sql_rel *l = rel->l; + sql_rel *r = rel->r; + + /* TODO make sure we do not have empty selects */ + if (is_simple_project(rel->op) && l && is_select(l->op) && exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) { + sql_rel *nl = rel_select(v->sql->sa, rel, NULL); + nl->exps = add_missing_project_exps(v->sql, rel, l->exps); + l->exps = NULL; + rel->l = rel_dup(l->l); + rel_destroy(l); + rel_bind_vars(v->sql, nl, nl->exps); + v->changes++; + return nl; + } + if (!is_single(rel) && is_innerjoin(rel->op) && l && is_select(l->op) && exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) { + sql_rel *nl = rel_select(v->sql->sa, rel, NULL); + nl->exps = l->exps; + l->exps = NULL; + rel->l = rel_dup(l->l); + rel_destroy(l); + rel_bind_vars(v->sql, nl, nl->exps); + v->changes++; + return nl; + } + if (is_single(rel) && is_innerjoin(rel->op) && l && is_select(l->op) && exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) { + if (rel->exps) + rel->exps = list_merge(rel->exps, l->exps, NULL); + else + rel->exps = l->exps; + l->exps = NULL; + rel->l = rel_dup(l->l); + rel_destroy(l); + rel_bind_vars(v->sql, rel, rel->exps); + v->changes++; + return rel; + } + if (!is_single(rel) && is_innerjoin(rel->op) && r && is_select(r->op) && exps_have_freevar(v->sql, r->exps) && !rel_is_ref(r)) { + sql_rel *nr = rel_select(v->sql->sa, rel, NULL); _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org