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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list