Changeset: 41f41926cf97 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/41f41926cf97 Modified Files: sql/server/rel_optimize_sel.c Branch: Aug2024 Log Message:
make sure we handle range joins correctly when reordering joins. diffs (157 lines): diff --git a/sql/server/rel_optimize_sel.c b/sql/server/rel_optimize_sel.c --- a/sql/server/rel_optimize_sel.c +++ b/sql/server/rel_optimize_sel.c @@ -2090,7 +2090,7 @@ popcount64(uint64_t x) static sql_rel * order_joins(visitor *v, list *rels, list *exps) { - sql_rel *top = NULL, *l = NULL, *r = NULL; + sql_rel *top = NULL, *l = NULL, *r = NULL, *f = NULL; sql_exp *cje; node *djn; list *sdje, *n_rels = NULL; @@ -2130,8 +2130,7 @@ order_joins(visitor *v, list *rels, list for (node *n = sdje->h; n; n = n->next, ci++) { sql_exp *cje = n->data; - h[ci] = r1[ci] = r2[ci] = 0; - r3[ci] = 0; + h[ci] = r1[ci] = r2[ci] = r3[ci] = 0; if (cje->type == e_cmp) { cje->tmp = ci; r1[ci] = cje->flag == cmp_filter ? exps_find_one_rel(rels_a, nr_rels, cje->l) : exp_find_one_rel(rels_a, nr_rels, cje->l); @@ -2142,7 +2141,7 @@ order_joins(visitor *v, list *rels, list h[ci] |= ((ulng)1)<<((r2[ci]-1)%64); if (cje->f && cje->flag != cmp_filter) { r3[ci] = exp_find_one_rel(rels_a, nr_rels, cje->f); - if (r3[ci] == r2[ci]) + if (r3[ci] == r2[ci] || r3[ci] == r1[ci]) r3[ci] = 0; if (r3[ci]) h[ci] |= ((ulng)1)<<((r3[ci]-1)%64); @@ -2155,13 +2154,15 @@ order_joins(visitor *v, list *rels, list for (node *n = sdje->h; n && !l && !r; n = n->next, ci++) { cje = n->data; - /* find the involved relations */ + if (n->next && r3[cje->tmp]) + continue; /* complex expressions may touch multiple base tables * Should be pushed up to extra selection. * */ if (0 && popcount64(h[cje->tmp]) > 2) assert(0); + /* find the involved relations */ if (cje->type == e_cmp) { l = rels_a[r1[cje->tmp]]; r = rels_a[r2[cje->tmp]]; @@ -2184,10 +2185,10 @@ order_joins(visitor *v, list *rels, list } /* Create a relation between l and r. Since the calling - functions rewrote the join tree, into a list of expressions - and a list of (simple) relations, there are no outer joins - involved, we can simply do a crossproduct here. - */ + functions rewrote the join tree, into a list of expressions + and a list of (simple) relations, there are no outer joins + involved, we can simply do a crossproduct here. + */ rsingle = is_single(r); reset_single(r); top = rel_crossproduct(v->sql->sa, l, r, op_join); @@ -2213,7 +2214,8 @@ order_joins(visitor *v, list *rels, list /* find the first expression which could be added */ for(djn = sdje->h; djn && !fnd && rels->h; djn = (!fnd)?djn->next:NULL) { node *en; - l = r = NULL; + l = r = f = NULL; + int needs3 = 0; cje = djn->data; if ((h[cje->tmp] & rel_mask) > 0) { @@ -2221,48 +2223,65 @@ order_joins(visitor *v, list *rels, list l = rels_a[r1[cje->tmp]]; if (rel_mask & (((ulng)1)<<((r2[cje->tmp]-1)%64))) r = rels_a[r2[cje->tmp]]; + if (cje->f && r3[cje->tmp] && (rel_mask & (((ulng)1)<<((r3[cje->tmp]-1)%64)))) { + f = rels_a[r3[cje->tmp]]; + needs3 = 1; + } } if (!direct) { /* check if at least one side in n_rels */ if (l && !list_find(n_rels, l, NULL)) l = NULL; if (r && !list_find(n_rels, r, NULL)) r = NULL; + if (f && !list_find(n_rels, f, NULL)) + f = NULL; } - if (l && r) { + if ((!needs3 && l && r) || (needs3 && l && r && f)) { assert(0); /* create a selection on the current */ rel_join_add_exp(v->sql->sa, top, cje); fnd = 1; - } else if (l || r) { - /* TODO: handle case for joins which need > 2 relations, ie where the current 'top' of the - * join tree needs to add more then one relation */ + } else if ((!needs3 && (l || r)) || (needs3 && (l || r || f))) { + sql_rel *nr[2]= {NULL, NULL}; rel_mask |= h[cje->tmp]; - if (l) { - r = rels_a[r2[cje->tmp]]; - } else { - l = r; - r = rels_a[r1[cje->tmp]]; - } - if (!r) { + int i = 0; + if (!l) + nr[i++] = rels_a[r1[cje->tmp]]; + if (!r) + nr[i++] = rels_a[r2[cje->tmp]]; + if (needs3 && !f) + nr[i++] = rels_a[r3[cje->tmp]]; + if (!nr[0]) { fnd = 1; /* not really, but this bails out */ list_remove_data(sdje, NULL, cje); /* handle later as select */ continue; } - /* remove the expression from the lists */ list_remove_data(sdje, NULL, cje); - list_remove_data(rels, NULL, r); + list_remove_data(rels, NULL, nr[0]); if (!direct) - append(n_rels, r); + append(n_rels, nr[0]); + if (i > 1 && nr[1]) { + list_remove_data(rels, NULL, nr[1]); + if (!direct) + append(n_rels, nr[1]); + } /* create a join using the current expression */ - rsingle = is_single(r); - reset_single(r); - top = rel_crossproduct(v->sql->sa, top, r, op_join); + rsingle = is_single(nr[0]); + reset_single(nr[0]); + top = rel_crossproduct(v->sql->sa, top, nr[0], op_join); if (rsingle) - set_single(r); + set_single(nr[0]); + if (i > 1 && nr[1]) { + rsingle = is_single(nr[1]); + reset_single(nr[1]); + top = rel_crossproduct(v->sql->sa, top, nr[1], op_join); + if (rsingle) + set_single(nr[1]); + } rel_join_add_exp(v->sql->sa, top, cje); /* all join expressions on these tables */ _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org