Changeset: 23a37f635d2b for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=23a37f635d2b Modified Files: gdk/gdk_hash.c gdk/gdk_storage.c geom/lib/libgeom.h geom/monetdb5/geom.c monetdb5/extras/rapi/rapi.c monetdb5/optimizer/opt_mergetable.c sql/backends/monet5/sql_statement.c sql/server/rel_optimizer.c sql/server/rel_rel.c sql/server/rel_unnest.c sql/server/sql_query.c sql/test/BugTracker-2008/Tests/select_not_wrong_result.SF-2080151.stable.out sql/test/subquery/Tests/subquery6.sql sql/test/subquery/Tests/subquery6.stable.out testing/Mtest.py.in tools/merovingian/daemon/handlers.c Branch: default Log Message:
Merged with Jun2020 diffs (truncated from 575 to 300 lines): diff --git a/gdk/gdk_hash.c b/gdk/gdk_hash.c --- a/gdk/gdk_hash.c +++ b/gdk/gdk_hash.c @@ -107,7 +107,11 @@ doHASHdestroy(BAT *b, Hash *hs) GDKunlink(BBPselectfarm(b->batRole, b->ttype, hashheap), BATDIR, BBP_physical(b->batCacheid), - "thash"); + "thashl"); + GDKunlink(BBPselectfarm(b->batRole, b->ttype, hashheap), + BATDIR, + BBP_physical(b->batCacheid), + "thashb"); } else if (hs) { bat p = VIEWtparent(b); BAT *hp = NULL; diff --git a/gdk/gdk_storage.c b/gdk/gdk_storage.c --- a/gdk/gdk_storage.c +++ b/gdk/gdk_storage.c @@ -887,10 +887,10 @@ BATdelete(BAT *b) assert(bid > 0); if (loaded) { b = loaded; - HASHdestroy(b); - IMPSdestroy(b); - OIDXdestroy(b); } + HASHdestroy(b); + IMPSdestroy(b); + OIDXdestroy(b); if (b->batCopiedtodisk || (b->theap.storage != STORE_MEM)) { if (b->ttype != TYPE_void && HEAPdelete(&b->theap, o, "tail") != GDK_SUCCEED && diff --git a/monetdb5/optimizer/opt_mergetable.c b/monetdb5/optimizer/opt_mergetable.c --- a/monetdb5/optimizer/opt_mergetable.c +++ b/monetdb5/optimizer/opt_mergetable.c @@ -1959,9 +1959,12 @@ OPTmergetableImplementation(Client cntxt bailout = 1; } if (getModuleId(p) == algebraRef && - getFunctionId(p) == thetajoinRef ) { + getFunctionId(p) == thetajoinRef) { + assert(p->argc == 9); + if (p->argc == 9 && getVarConstant(mb,getArg(p,6)).val.ival == 6 /* op == '<>' */) { TRC_INFO(MAL_OPTIMIZER, "Mergetable bailout thetajoin ref\n"); bailout = 1; + } } if (isSample(p)) { bailout = 1; diff --git a/sql/backends/monet5/sql_statement.c b/sql/backends/monet5/sql_statement.c --- a/sql/backends/monet5/sql_statement.c +++ b/sql/backends/monet5/sql_statement.c @@ -2036,8 +2036,11 @@ stmt_semijoin(backend *be, stmt *op1, st if (op1->nr < 0 || op2->nr < 0) return NULL; - q = newStmt(mb, algebraRef, semijoinRef); - q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any)); + if (single) { + q = newStmt(mb, algebraRef, semijoinRef); + q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any)); + } else + q = newStmt(mb, algebraRef, intersectRef); q = pushArgument(mb, q, op1->nr); q = pushArgument(mb, q, op2->nr); if (lcand) @@ -2060,7 +2063,9 @@ stmt_semijoin(backend *be, stmt *op1, st s->op2 = op2; s->flag = cmp_equal; s->key = 0; - s->nrcols = 2; + s->nrcols = 1; + if (single) + s->nrcols = 2; s->nr = getDestVar(q); s->q = q; return s; 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 @@ -4101,7 +4101,7 @@ rel_merge_rse(mvc *sql, sql_rel *rel, in /* find in the list of expression an expression which uses e */ static sql_exp * -exp_uses_exp( list *exps, sql_exp *e) +exps_uses_exp( list *exps, sql_exp *e) { node *n; const char *rname = exp_relname(e); @@ -4246,7 +4246,7 @@ rel_push_aggr_down(mvc *sql, sql_rel *re for (n = ogbe->h; n; n = n->next) { sql_exp *e = n->data, *ne; - ne = exp_uses_exp( rel->exps, e); + ne = exps_uses_exp( rel->exps, e); if (!ne) continue; ne = list_find_exp( u->exps, ne); @@ -4780,11 +4780,11 @@ rel_push_join_down(mvc *sql, sql_rel *re /* project in between, ie find alias */ /* first find expression in expression list */ - gbe = exp_uses_exp( gb->exps, gbe); + gbe = exps_uses_exp( gb->exps, gbe); if (!gbe) continue; if (ogb != gb) - gbe = exp_uses_exp( ogb->exps, gbe); + gbe = exps_uses_exp( ogb->exps, gbe); if (gbe) { rname = exp_find_rel_name(gbe); name = exp_name(gbe); @@ -5340,6 +5340,96 @@ rel_remove_empty_join(mvc *sql, sql_rel return rel; } +/* const or groupby without group by exps */ +#define SIMPLE_PROJECTION_FOR_JOIN2SEMI(X) \ + ((X)->card < CARD_AGGR && is_project((X)->op) && list_length((X)->exps) == 1) + +static sql_rel * +find_candidate_join2semi(sql_rel *rel, bool *swap) +{ + /* generalize possibility : we need the visitor 'step' here */ + if (rel->op == op_join && rel->exps) { + sql_rel *l = rel->l, *r = rel->r; + + if (SIMPLE_PROJECTION_FOR_JOIN2SEMI(r)) { + *swap = false; + return rel; + } + if (SIMPLE_PROJECTION_FOR_JOIN2SEMI(l)) { + *swap = true; + return rel; + } + } + if (is_join(rel->op) || is_semi(rel->op)) { + sql_rel *c; + + if ((c=find_candidate_join2semi(rel->l, swap)) != NULL || + (c=find_candidate_join2semi(rel->r, swap)) != NULL) + return c; + } + return NULL; +} + +static int +subrel_uses_exp_outside_subrel(sql_rel *rel, sql_exp *e, sql_rel *c) +{ + if (rel == c) + return 0; + /* for subrel only expect joins (later possibly selects) */ + if (is_join(rel->op) || is_semi(rel->op)) { + if (exps_uses_exp(rel->exps, e)) + return 1; + if (subrel_uses_exp_outside_subrel(rel->l, e, c) || + subrel_uses_exp_outside_subrel(rel->r, e, c)) + return 1; + } + return 0; +} + +static int +rel_uses_exp_outside_subrel(sql_rel *rel, sql_exp *e, sql_rel *c) +{ + /* for now we only expect sub relations of type project, selects (rel) or join/semi */ + if (is_simple_project(rel->op) || is_groupby(rel->op) || is_select(rel->op)) { + if (!list_empty(rel->exps) && exps_uses_exp(rel->exps, e)) + return 1; + if ((is_simple_project(rel->op) || is_groupby(rel->op)) && !list_empty(rel->r) && exps_uses_exp(rel->r, e)) + return 1; + if (rel->l) + return subrel_uses_exp_outside_subrel(rel->l, e, c); + } + return 1; +} + +static sql_rel * +rel_join2semijoin(mvc *sql, sql_rel *rel, int *changes) +{ + (void)sql; + if ((is_simple_project(rel->op) || is_groupby(rel->op) || is_select(rel->op)) && rel->l) { + bool swap = false; + sql_rel *l = rel->l; + sql_rel *c = find_candidate_join2semi(l, &swap); + + if (c) { + /* 'p' is a project and only has one result */ + sql_rel *p = swap ? c->l : c->r; + sql_exp *re = p->exps->h->data; + + /* now we need to check if ce is only used at the level of c */ + if (!rel_uses_exp_outside_subrel(rel, re, c)) { + c->op = op_semi; + if (swap) { + sql_rel *tmp = c->r; + c->r = c->l; + c->l = tmp; + } + (*changes)++; + } + } + } + return rel; +} + typedef struct { sql_rel *p; /* the found join's parent */ sql_rel *j; /* the found join relation itself */ @@ -9076,6 +9166,8 @@ optimize_rel(mvc *sql, sql_rel *rel, int if (gp.cnt[op_join] || gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full] || gp.cnt[op_semi] || gp.cnt[op_anti]) { rel = rel_remove_empty_join(sql, rel, &changes); + + rel = rel_visitor_bottomup(sql, rel, &rel_join2semijoin, &changes); if (!gp.cnt[op_update]) rel = rel_join_order(sql, rel); rel = rel_visitor_bottomup(sql, rel, &rel_push_join_down_union, &changes); 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 @@ -432,6 +432,7 @@ rel_inplace_project(sql_allocator *sa, s return NULL; *l = *rel; + l->ref.refcnt = 1; } else { rel_destroy_(rel); } 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 @@ -732,6 +732,14 @@ rel_general_unnest(mvc *sql, sql_rel *re int nr; sql_rel *l = rel->l, *r = rel->r, *inner_r; + + /* cleanup empty selects (should be done before any rel_dup(l) */ + if (l && is_select(l->op) && list_empty(l->exps) && !rel_is_ref(l)) { + rel->l = l->l; + l->l = NULL; + rel_destroy(l); + l = rel->l; + } /* 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); @@ -1480,7 +1488,7 @@ rel_unnest_dependent(mvc *sql, sql_rel * return rel_unnest_dependent(sql, rel); } - if (r && is_groupby(r->op) && need_distinct(l) /*&& is_distinct_set(sql, l, ad)*/) { + if (r && is_groupby(r->op) && !is_left(rel->op) && is_distinct_set(sql, l, ad)) { rel = push_up_groupby(sql, rel, ad); return rel_unnest_dependent(sql, rel); } @@ -1490,7 +1498,7 @@ rel_unnest_dependent(mvc *sql, sql_rel * return rel_unnest_dependent(sql, rel); } - if (r && is_set(r->op) && (!is_left(rel->op) && is_distinct_set(sql, l, ad))) { + if (r && is_set(r->op) && !is_left(rel->op) && is_distinct_set(sql, l, ad)) { rel = push_up_set(sql, rel, ad); return rel_unnest_dependent(sql, rel); } @@ -2333,7 +2341,7 @@ rewrite_compare(mvc *sql, sql_rel *rel, } else { if (lsq) (void)rewrite_inner(sql, rel, lsq, op_join); - if (rsq) + if (rsq) (void)rewrite_inner(sql, rel, rsq, !is_tuple?op_join:is_anyequal(sf)?op_semi:op_anti); if (is_tuple) { list *t = le->f; @@ -3034,6 +3042,8 @@ rel_unnest(mvc *sql, sql_rel *rel) 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 */ + if (changes > 0) + rel = rel_visitor_bottomup(sql, rel, &rel_remove_empty_select, &changes); rel = rel_visitor_bottomup(sql, rel, &rewrite_compare_exp, &changes); /* only allow for e_cmp in selects and handling */ rel = rel_visitor_bottomup(sql, rel, &rewrite_remove_xp_project, &changes); /* remove crossproducts with project ( project [ atom ] ) [ etc ] */ changes = 0; diff --git a/sql/server/sql_query.c b/sql/server/sql_query.c --- a/sql/server/sql_query.c +++ b/sql/server/sql_query.c @@ -102,10 +102,10 @@ query_outer_used_exp(sql_query *q, int i sq->last_used = e; sq->used_card = sq->rel->card; - assert( (!is_sql_aggr(f) && sq->grouped == 0 && e->card > CARD_AGGR) || /* outer is a none grouped relation */ + assert( (!is_sql_aggr(f) && sq->grouped == 0 && e->card != CARD_AGGR) || /* outer is a none grouped relation */ (!is_sql_aggr(f) && sq->grouped == 1 && e->card <= CARD_AGGR) || /* outer is groupbed, ie only return aggregations or groupby cols */ - (is_sql_aggr(f) && !is_sql_farg(f) && !sq->grouped && e->card > CARD_AGGR) || /* a column to be aggregated */ - (is_sql_aggr(f) && !is_sql_farg(f) && sq->grouped && e->card > CARD_AGGR) || /* a column to be aggregated */ + (is_sql_aggr(f) && !is_sql_farg(f) && !sq->grouped && e->card != CARD_AGGR) || /* a column/constant to be aggregated */ + (is_sql_aggr(f) && !is_sql_farg(f) && sq->grouped && e->card != CARD_AGGR) || /* a column/constant to be aggregated */ (is_sql_aggr(f) && is_sql_farg(f) && sq->grouped && e->card <= CARD_AGGR) || /* groupby ( function (group by col)) */ (is_sql_aggr(f) && sq->grouped && e->card <= CARD_AGGR) ); /* nested aggregations is handled later */ _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list