Changeset: 8c7d4e3a2133 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/8c7d4e3a2133 Added Files: sql/test/miscellaneous/Tests/anti_join_plan.test Modified Files: sql/server/rel_optimize_proj.c sql/storage/bat/bat_storage.c sql/test/Tests/select_window_pushdown.test sql/test/mergetables/Tests/mergequery.test sql/test/miscellaneous/Tests/All sql/test/miscellaneous/Tests/simple_plans.test sql/test/miscellaneous/Tests/unique_keys.test sql/test/prepare/Tests/prepare-utf8.Bug-3930.stable.out sql/test/prepare/Tests/prepared-statement-with-udf.Bug-6650.stable.out Branch: default Log Message:
add simple optimizer to rewrite column expressions into constants when there is a col=constant select unter the project diffs (truncated from 383 to 300 lines): diff --git a/sql/server/rel_optimize_proj.c b/sql/server/rel_optimize_proj.c --- a/sql/server/rel_optimize_proj.c +++ b/sql/server/rel_optimize_proj.c @@ -2983,10 +2983,41 @@ rel_groupjoin(visitor *v, sql_rel *rel) return rel; } +/* select k1 from bla where k1 = const -> select const from bla where k1 = const */ +static sql_rel * +rel_project_select_exp(visitor *v, sql_rel *rel) +{ + if (is_simple_project(rel->op) && rel->exps && rel->l) { + sql_rel *l = rel->l; + if (is_select(l->op) && l->exps) { + for(node *n = rel->exps->h; n; n = n->next) { + sql_exp *col = n->data; + if (col->type == e_column) { + for(node *m = l->exps->h; m; m = m->next) { + sql_exp *cmp = m->data; + if (cmp->type == e_cmp && cmp->flag == cmp_equal && !is_anti(cmp) && !is_semantics(cmp) && exp_is_atom(cmp->r)) { + sql_exp *l = cmp->l; + if(l->type == e_column && ((!col->l && !l->l) || (col->l && l->l && strcmp(col->l, l->l) == 0)) && strcmp(col->r, l->r) == 0) { + /* replace column with the constant */ + sql_exp *e = n->data = exp_copy(v->sql, cmp->r); + exp_setname(v->sql->sa, e, exp_relname(col), exp_name(col)); + exp_propagate(v->sql->sa, e, col); + list_hash_clear(rel->exps); + } + } + } + } + } + } + } + return rel; +} + static sql_rel * rel_optimize_projections_(visitor *v, sql_rel *rel) { rel = rel_project_cse(v, rel); + rel = rel_project_select_exp(v, rel); if (!rel || !is_groupby(rel->op)) return rel; diff --git a/sql/storage/bat/bat_storage.c b/sql/storage/bat/bat_storage.c --- a/sql/storage/bat/bat_storage.c +++ b/sql/storage/bat/bat_storage.c @@ -493,6 +493,8 @@ segs_end( segments *segs, sql_trans *tr, { size_t cnt = 0; + /* because a table can grow rows over the time a transaction is running, we need to find the last valid segment, to + * keep all of the parts aligned */ lock_table(tr->store, table->base.id); segment *s = segs->h, *l = NULL; diff --git a/sql/test/Tests/select_window_pushdown.test b/sql/test/Tests/select_window_pushdown.test --- a/sql/test/Tests/select_window_pushdown.test +++ b/sql/test/Tests/select_window_pushdown.test @@ -26,11 +26,11 @@ project ( | | | | | select ( | | | | | | table("sys"."test") [ "test"."k" NOT NULL, "test"."v" NOT NULL UNIQUE ] | | | | | ) [ ("test"."k" NOT NULL) = (int(31) "10") ] -| | | | ) [ "test"."k" NOT NULL as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] +| | | | ) [ int(31) "10" as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] -| | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] +| | ) [ "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ int(31) "10" as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # simple range filter on the partition key query T nosort @@ -56,7 +56,7 @@ project ( | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # simple not in filter on the partition key query T nosort @@ -82,7 +82,7 @@ project ( | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # another filter also not on the partition key, must not be pushed down query T nosort @@ -104,11 +104,11 @@ project ( | | | | | select ( | | | | | | table("sys"."test") [ "test"."k" NOT NULL, "test"."v" NOT NULL UNIQUE ] | | | | | ) [ ("test"."k" NOT NULL) = (int(31) "10") ] -| | | | ) [ "test"."k" NOT NULL as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] +| | | | ) [ int(31) "10" as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] -| | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] +| | ) [ "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."v" NOT NULL UNIQUE) = (int(31) "15"), ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ int(31) "10" as "t2"."k", int(31) "15" as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # swapping k with v just to test for hardcoded optimizations, # v is pushed down but not k @@ -131,11 +131,11 @@ project ( | | | | | select ( | | | | | | table("sys"."test") [ "test"."k" NOT NULL, "test"."v" NOT NULL UNIQUE ] | | | | | ) [ ("test"."v" NOT NULL UNIQUE) = (int(31) "15") ] -| | | | ) [ "test"."k" NOT NULL as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] +| | | | ) [ "test"."k" NOT NULL as "t1"."k", int(31) "15" as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."v" NULLS LAST NOT NULL UNIQUE ] -| | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."v" NOT NULL UNIQUE), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] +| | ) [ "t1"."k" NOT NULL, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."v" NOT NULL UNIQUE), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1"), ("t1"."k" NOT NULL) = (int(31) "10") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ int(31) "10" as "t2"."k", int(31) "15" as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # performing some additional computation on the partition key, # filter cannot be pushed down @@ -162,9 +162,9 @@ project ( | | | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] | | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | | | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -| | ) [ "sys"."sql_mul"("t1"."k" NOT NULL, tinyint(4) "10") NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +| | ) [ "sys"."sql_mul"("t1"."k" NOT NULL, tinyint(4) "10") NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v" ] | ) [ ("t2"."k" NOT NULL) = (bigint(35) "10") ] -) [ "t2"."k" NOT NULL, "t2"."v" NOT NULL UNIQUE, "t2"."flag" NOT NULL, "t2"."rank" NOT NULL ] +) [ bigint(35) "10" as "t2"."k", "t2"."v" NOT NULL UNIQUE, boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # filter [partition column OR flag], cannot be safely pushed down query T nosort @@ -188,7 +188,7 @@ project ( | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t2"."rank") = (int(31) "1"), (("t1"."flag" NOT NULL) = (boolean(1) "false")) or (("t1"."k" NOT NULL) = (int(31) "10")) ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", int(31) "1" as "t2"."rank" ] # filter on k and v and both are partition columns, both filters can be pushed down query T nosort @@ -214,7 +214,7 @@ project ( | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("sys"."diff"("t1"."k" NOT NULL), "t1"."v" NOT NULL UNIQUE), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] statement ok DROP TABLE Test @@ -246,11 +246,11 @@ project ( | | | | | select ( | | | | | | table("sys"."test") [ "test"."k" NOT NULL, "test"."v" NOT NULL UNIQUE ] | | | | | ) [ ("test"."k" NOT NULL) = (varchar(100) "10") ] -| | | | ) [ "test"."k" NOT NULL as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] +| | | | ) [ varchar(100) "10" as "t1"."k", "test"."v" NOT NULL UNIQUE as "t1"."v", "sys"."mod"("test"."v" NOT NULL UNIQUE, int(2) "2") NOT NULL as "%1"."%1", "sys"."="("%1"."%1" NOT NULL, int(31) "0") NOT NULL as "t1"."flag" ] | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] -| | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] +| | ) [ "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ varchar(100) "10" as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] # test with like-type filters query T nosort @@ -276,7 +276,7 @@ project ( | | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL ] [ "t1"."k" ASC NOT NULL, "t1"."v" NULLS LAST NOT NULL UNIQUE ] | | ) [ "t1"."k" NOT NULL, "t1"."v" NOT NULL UNIQUE, "t1"."flag" NOT NULL, "sys"."rank"(varchar["sys"."star"()], "sys"."diff"("t1"."k" NOT NULL), "sys"."diff"("t1"."v" NOT NULL UNIQUE)) as "t2"."rank" ] | ) [ ("t1"."flag" NOT NULL) = (boolean(1) "false"), ("t2"."rank") = (int(31) "1") ] -) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", "t1"."flag" NOT NULL as "t2"."flag", "t2"."rank" NOT NULL ] +) [ "t1"."k" NOT NULL as "t2"."k", "t1"."v" NOT NULL UNIQUE as "t2"."v", boolean(1) "false" as "t2"."flag", int(31) "1" as "t2"."rank" ] statement ok DROP TABLE Test diff --git a/sql/test/mergetables/Tests/mergequery.test b/sql/test/mergetables/Tests/mergequery.test --- a/sql/test/mergetables/Tests/mergequery.test +++ b/sql/test/mergetables/Tests/mergequery.test @@ -111,7 +111,7 @@ project ( | select ( | | table("sys"."part1") [ "part1"."x" NOT NULL as "complete"."x", "part1"."y" NOT NULL as "complete"."y", "part1"."z" NOT NULL as "complete"."z" ] | ) [ ("complete"."x" NOT NULL) = (double(53) "0") ] -) [ "complete"."x" NOT NULL, "complete"."y" NOT NULL, "complete"."z" NOT NULL ] +) [ double(53) "0" as "complete"."x", "complete"."y" NOT NULL, "complete"."z" NOT NULL ] query RRR rowsort SELECT * FROM complete where x = 0.0 @@ -130,7 +130,7 @@ project ( | select ( | | table("sys"."part2") [ "part2"."x" NOT NULL as "complete"."x", "part2"."y" NOT NULL as "complete"."y", "part2"."z" NOT NULL as "complete"."z" ] | ) [ ("complete"."x" NOT NULL) = (double(53) "3") ] -) [ "complete"."x" NOT NULL, "complete"."y" NOT NULL, "complete"."z" NOT NULL ] +) [ double(53) "3" as "complete"."x", "complete"."y" NOT NULL, "complete"."z" NOT NULL ] query RRR rowsort SELECT * FROM complete where x = 3.0 diff --git a/sql/test/miscellaneous/Tests/All b/sql/test/miscellaneous/Tests/All --- a/sql/test/miscellaneous/Tests/All +++ b/sql/test/miscellaneous/Tests/All @@ -27,5 +27,6 @@ sequences analyze_test blobs temp_tables +anti_join_plan table_alias_on_cte special_character_names diff --git a/sql/test/miscellaneous/Tests/anti_join_plan.test b/sql/test/miscellaneous/Tests/anti_join_plan.test new file mode 100644 --- /dev/null +++ b/sql/test/miscellaneous/Tests/anti_join_plan.test @@ -0,0 +1,89 @@ +# init +statement ok +CREATE TABLE Test (k1 int, k2 int, k3 int, v int) + +statement ok +INSERT INTO Test SELECT value % 10 as k1, value % 100 as k2, value % 1000 as k3, value as v FROM generate_series(1, 100000) + +statement ok +set optimizer='sequential_pipe' + +# unoptimized anti join +query T python .explain.function_histogram +explain select * from test +where (k1, k2) not in ( + select k1, k2 + from test + where k1 = 1 +) +---- +algebra.difference +2 +algebra.join +1 +algebra.project +1 +algebra.projection +9 +algebra.projectionpath +3 +algebra.select +1 +algebra.thetaselect +2 +bat.mirror +1 +bat.pack +5 +batcalc.ifthenelse +1 +batcalc.not +1 +querylog.define +1 +sql.bind +4 +sql.mvc +1 +sql.resultSet +1 +sql.tid +1 +user.main +1 + +# optimized anti join +query T python .explain.function_histogram +explain select * from test +where k2 not in ( + select k2 + from test + where k1 = 1 +) +---- +algebra.difference +1 +algebra.projection +3 +algebra.projectionpath +3 +algebra.thetaselect +1 +bat.pack +5 +querylog.define +1 +sql.bind +4 +sql.mvc +1 +sql.resultSet +1 +sql.tid +1 +user.main +1 + +statement ok _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org