Changeset: a4374e43f2d4 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a4374e43f2d4 Modified Files: sql/backends/monet5/rel_bin.c sql/benchmarks/tpch/Tests/02-explain.stable.out sql/benchmarks/tpch/Tests/02-plan.stable.out sql/benchmarks/tpch/Tests/10-plan.stable.out sql/benchmarks/tpch/Tests/17-explain.stable.out sql/benchmarks/tpch/Tests/17-plan.stable.out sql/benchmarks/tpch/Tests/18-plan.stable.out sql/benchmarks/tpch/Tests/20-explain.stable.out sql/benchmarks/tpch/Tests/20-plan.stable.out sql/benchmarks/tpch/Tests/21-plan.stable.out sql/server/rel_exp.c sql/server/rel_exp.h sql/server/rel_optimizer.c Branch: Oct2014 Log Message:
added an other push groupby down rewrite step. When a groupby follows a join, and the group by is grouped over a unique column of one of the joined tables (and all aggregates are done on this table), it can be pushed down. This pattern happens a lot after apply rewrites (ie of correlated subqueries). One thing to remember is when pushed down 'outer' joins we should mark 'count' aggregates as the outer join should after the rewrite fill in '0' and not 'null' when rows are missing. diffs (truncated from 1342 to 300 lines): diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c --- a/sql/backends/monet5/rel_bin.c +++ b/sql/backends/monet5/rel_bin.c @@ -28,6 +28,8 @@ #include "rel_optimizer.h" #include "sql_env.h" +#define OUTER_ZERO 64 + static stmt * subrel_bin(mvc *sql, sql_rel *rel, list *refs); static stmt * @@ -526,6 +528,8 @@ exp_bin(mvc *sql, sql_exp *e, stmt *left } } s = stmt_aggr(sql->sa, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/ ); + if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */ + s->flag |= OUTER_ZERO; /* HACK: correct cardinality for window functions */ if (e->card > CARD_AGGR) s->nrcols = 2; @@ -1083,6 +1087,7 @@ stmt_rename(mvc *sql, sql_rel *rel, sql_ { char *name = exp->name; char *rname = exp->rname; + stmt *o = s; (void)rel; if (!name && exp->type == e_column && exp->r) @@ -1094,6 +1099,8 @@ stmt_rename(mvc *sql, sql_rel *rel, sql_ if (!rname) rname = table_name(sql->sa, s); s = stmt_alias(sql->sa, s, rname, name); + if (o->flag & OUTER_ZERO) + s->flag |= OUTER_ZERO; return s; } @@ -1645,7 +1652,7 @@ rel2bin_join( mvc *sql, sql_rel *rel, li if (rel->op == op_left || rel->op == op_full) s = stmt_append(sql->sa, s, stmt_project(sql->sa, ld, c)); if (rel->op == op_right || rel->op == op_full) - s = stmt_append(sql->sa, s, stmt_const(sql->sa, rd, stmt_atom(sql->sa, atom_general(sql->sa, tail_type(c), NULL)))); + s = stmt_append(sql->sa, s, stmt_const(sql->sa, rd, (c->flag&OUTER_ZERO)?stmt_atom_wrd(sql->sa, 0):stmt_atom(sql->sa, atom_general(sql->sa, tail_type(c), NULL)))); s = stmt_alias(sql->sa, s, rnme, nme); list_append(l, s); @@ -1660,7 +1667,7 @@ rel2bin_join( mvc *sql, sql_rel *rel, li if (rel->op == op_left || rel->op == op_full || rel->op == op_right) s = Column(sql->sa, s); if (rel->op == op_left || rel->op == op_full) - s = stmt_append(sql->sa, s, stmt_const(sql->sa, ld, stmt_atom(sql->sa, atom_general(sql->sa, tail_type(c), NULL)))); + s = stmt_append(sql->sa, s, stmt_const(sql->sa, ld, (c->flag&OUTER_ZERO)?stmt_atom_wrd(sql->sa, 0):stmt_atom(sql->sa, atom_general(sql->sa, tail_type(c), NULL)))); if (rel->op == op_right || rel->op == op_full) s = stmt_append(sql->sa, s, stmt_project(sql->sa, rd, c)); diff --git a/sql/benchmarks/tpch/Tests/02-explain.stable.out b/sql/benchmarks/tpch/Tests/02-explain.stable.out --- a/sql/benchmarks/tpch/Tests/02-explain.stable.out +++ b/sql/benchmarks/tpch/Tests/02-explain.stable.out @@ -67,168 +67,167 @@ Ready. % 823 # length function user.s2_1{autoCommit=true}(A0:int,A1:str,A2:str,A3:str):void; X_6 := sql.mvc(); - X_7:bat[:oid,:oid] := sql.tid(X_6,"sys","nation"); - X_10 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",0); - (X_13,r1_13) := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",2); - X_16 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",1); - X_18 := sql.projectdelta(X_7,X_10,X_13,r1_13,X_16); - X_21 := sql.bind(X_6,"sys","region","r_name",0); - X_19:bat[:oid,:oid] := sql.tid(X_6,"sys","region"); - X_337 := algebra.subselect(X_21,X_19,A3,A3,true,true,false); - (X_23,r1_24) := sql.bind(X_6,"sys","region","r_name",2); - X_338 := algebra.subselect(r1_24,A3,A3,true,true,false); - X_25 := sql.bind(X_6,"sys","region","r_name",1); - X_339 := algebra.subselect(X_25,X_19,A3,A3,true,true,false); - X_26 := sql.subdelta(X_337,X_19,X_23,X_338,X_339); - X_28 := X_26; - (X_29,r1_33) := algebra.join(X_18,X_28); - X_31 := algebra.leftfetchjoin(X_29,X_7); - X_32:bat[:oid,:oid] := sql.tid(X_6,"sys","supplier"); - X_34 := sql.bind_idxbat(X_6,"sys","supplier","supplier_s_nationkey_fkey",0); - (X_36,r1_40) := sql.bind_idxbat(X_6,"sys","supplier","supplier_s_nationkey_fkey",2); - X_39 := sql.bind_idxbat(X_6,"sys","supplier","supplier_s_nationkey_fkey",1); - X_40 := sql.projectdelta(X_32,X_34,X_36,r1_40,X_39); - (X_41,r1_46) := algebra.join(X_31,X_40); - X_43 := algebra.leftfetchjoin(r1_46,X_32); - X_44:bat[:oid,:oid] := sql.tid(X_6,"sys","partsupp"); - X_46 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_suppkey_fkey",0); - (X_49,r1_54) := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_suppkey_fkey",2); - X_52 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_suppkey_fkey",1); - X_54 := sql.projectdelta(X_44,X_46,X_49,r1_54,X_52); - (X_55,r1_61) := algebra.join(X_43,X_54); - X_57 := sql.bind(X_6,"sys","partsupp","ps_partkey",0); - (X_59,r1_65) := sql.bind(X_6,"sys","partsupp","ps_partkey",2); - X_61 := sql.bind(X_6,"sys","partsupp","ps_partkey",1); - X_62 := sql.projectdelta(X_44,X_57,X_59,r1_65,X_61); - X_63 := algebra.leftfetchjoin(r1_61,X_62); - X_64 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_partkey_fkey",0); - (X_66,r1_74) := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_partkey_fkey",2); - X_69 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_partkey_fkey",1); - X_70 := sql.projectdelta(X_44,X_64,X_66,r1_74,X_69); - X_73 := sql.bind(X_6,"sys","part","p_type",0); - X_79 := sql.bind(X_6,"sys","part","p_size",0); - X_71:bat[:oid,:oid] := sql.tid(X_6,"sys","part"); - X_340 := algebra.subselect(X_79,X_71,A0,A0,true,true,false); - (X_82,r1_95) := sql.bind(X_6,"sys","part","p_size",2); - X_341 := algebra.subselect(r1_95,A0,A0,true,true,false); - X_85 := sql.bind(X_6,"sys","part","p_size",1); - X_342 := algebra.subselect(X_85,X_71,A0,A0,true,true,false); - X_87 := sql.subdelta(X_340,X_71,X_82,X_341,X_342); - X_343 := algebra.likesubselect(X_73,X_87,A1,"",false); - (X_75,r1_84) := sql.bind(X_6,"sys","part","p_type",2); - X_344 := algebra.likesubselect(r1_84,A1,"",false); - X_77 := sql.bind(X_6,"sys","part","p_type",1); - X_345 := algebra.likesubselect(X_77,X_87,A1,"",false); - X_90 := sql.subdelta(X_343,X_87,X_75,X_344,X_345); - X_91 := X_90; - (X_92,r1_108) := algebra.join(X_70,X_91); - X_95 := algebra.leftfetchjoin(X_92,X_54); - (X_96,r1_122) := algebra.join(X_95,X_32); - X_98 := algebra.leftfetchjoin(r1_122,X_40); - X_99:bat[:oid,:oid] := sql.tid(X_6,"sys","nation"); - (X_101,r1_134) := algebra.join(X_98,X_99); - X_103 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",0); - (X_106,r1_139) := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",2); - X_109 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",1); - X_111 := sql.projectdelta(X_99,X_103,X_106,r1_139,X_109); - X_112 := algebra.leftfetchjoin(r1_134,X_111); - X_116 := sql.bind(X_6,"sys","region","r_name",0); - X_113:bat[:oid,:oid] := sql.tid(X_6,"sys","region"); - X_346 := algebra.subselect(X_116,X_113,A2,A2,true,true,false); - (X_118,r1_152) := sql.bind(X_6,"sys","region","r_name",2); - X_347 := algebra.subselect(r1_152,A2,A2,true,true,false); - X_120 := sql.bind(X_6,"sys","region","r_name",1); - X_348 := algebra.subselect(X_120,X_113,A2,A2,true,true,false); - X_121 := sql.subdelta(X_346,X_113,X_118,X_347,X_348); - X_124 := X_121; - (X_125,r1_162) := algebra.join(X_112,X_124); - X_349 := algebra.leftfetchjoin(X_125,X_101); - X_127 := sql.bind(X_6,"sys","part","p_partkey",0); - (X_130,r1_167) := sql.bind(X_6,"sys","part","p_partkey",2); - X_132 := sql.bind(X_6,"sys","part","p_partkey",1); - X_133 := sql.projectdelta(X_90,X_127,X_130,r1_167,X_132); - X_134:bat[:oid,:int] := algebra.leftfetchjoinPath(X_349,X_96,r1_108,X_133); - (X_135,r1_177) := algebra.join(X_63,X_134); - X_137:bat[:oid,:oid] := batcalc.identity(X_134); - X_138 := algebra.leftfetchjoin(r1_177,X_137); - (X_139,r1_183,r2_183) := group.subgroupdone(X_138); - X_350 := algebra.leftfetchjoin(r1_183,r1_177); - X_142 := sql.bind(X_6,"sys","partsupp","ps_supplycost",0); - (X_147,r1_191) := sql.bind(X_6,"sys","partsupp","ps_supplycost",2); - X_150 := sql.bind(X_6,"sys","partsupp","ps_supplycost",1); - X_152 := sql.projectdelta(X_44,X_142,X_147,r1_191,X_150); - X_154:bat[:oid,:lng] := algebra.leftfetchjoinPath(X_135,r1_61,X_152); - X_155:bat[:oid,:lng] := aggr.submin(X_154,X_139,r1_183,true); - X_153:bat[:oid,:lng] := algebra.leftfetchjoinPath(X_350,X_125,X_101,X_96,X_92,X_152); - X_157:bat[:oid,:bit] := batcalc.==(X_153,X_155); - X_158 := algebra.subselect(X_157,true,true,true,true,false); - X_351 := algebra.leftfetchjoin(X_158,r1_183); - X_160:bat[:oid,:int] := algebra.leftfetchjoinPath(X_351,r1_177,X_134); + X_10 := sql.bind(X_6,"sys","part","p_type",0); + X_19 := sql.bind(X_6,"sys","part","p_size",0); + X_7:bat[:oid,:oid] := sql.tid(X_6,"sys","part"); + X_334 := algebra.subselect(X_19,X_7,A0,A0,true,true,false); + (X_21,r1_25) := sql.bind(X_6,"sys","part","p_size",2); + X_335 := algebra.subselect(r1_25,A0,A0,true,true,false); + X_23 := sql.bind(X_6,"sys","part","p_size",1); + X_336 := algebra.subselect(X_23,X_7,A0,A0,true,true,false); + X_24 := sql.subdelta(X_334,X_7,X_21,X_335,X_336); + X_337 := algebra.likesubselect(X_10,X_24,A1,"",false); + (X_13,r1_13) := sql.bind(X_6,"sys","part","p_type",2); + X_338 := algebra.likesubselect(r1_13,A1,"",false); + X_16 := sql.bind(X_6,"sys","part","p_type",1); + X_339 := algebra.likesubselect(X_16,X_24,A1,"",false); + X_26 := sql.subdelta(X_337,X_24,X_13,X_338,X_339); + X_27 := sql.bind(X_6,"sys","part","p_partkey",0); + (X_29,r1_36) := sql.bind(X_6,"sys","part","p_partkey",2); + X_31 := sql.bind(X_6,"sys","part","p_partkey",1); + X_32 := sql.projectdelta(X_26,X_27,X_29,r1_36,X_31); + X_33:bat[:oid,:oid] := sql.tid(X_6,"sys","nation"); + X_36 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",0); + (X_39,r1_48) := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",2); + X_42 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",1); + X_44 := sql.projectdelta(X_33,X_36,X_39,r1_48,X_42); + X_47 := sql.bind(X_6,"sys","region","r_name",0); + X_45:bat[:oid,:oid] := sql.tid(X_6,"sys","region"); + X_340 := algebra.subselect(X_47,X_45,A3,A3,true,true,false); + (X_49,r1_59) := sql.bind(X_6,"sys","region","r_name",2); + X_341 := algebra.subselect(r1_59,A3,A3,true,true,false); + X_51 := sql.bind(X_6,"sys","region","r_name",1); + X_342 := algebra.subselect(X_51,X_45,A3,A3,true,true,false); + X_52 := sql.subdelta(X_340,X_45,X_49,X_341,X_342); + X_55 := X_52; + (X_56,r1_69) := algebra.join(X_44,X_55); + X_58 := algebra.leftfetchjoin(X_56,X_33); + X_59:bat[:oid,:oid] := sql.tid(X_6,"sys","supplier"); + X_61 := sql.bind_idxbat(X_6,"sys","supplier","supplier_s_nationkey_fkey",0); + (X_63,r1_76) := sql.bind_idxbat(X_6,"sys","supplier","supplier_s_nationkey_fkey",2); + X_66 := sql.bind_idxbat(X_6,"sys","supplier","supplier_s_nationkey_fkey",1); + X_67 := sql.projectdelta(X_59,X_61,X_63,r1_76,X_66); + (X_68,r1_82) := algebra.join(X_58,X_67); + X_70 := algebra.leftfetchjoin(r1_82,X_59); + X_71:bat[:oid,:oid] := sql.tid(X_6,"sys","partsupp"); + X_73 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_suppkey_fkey",0); + (X_76,r1_90) := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_suppkey_fkey",2); + X_79 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_suppkey_fkey",1); + X_81 := sql.projectdelta(X_71,X_73,X_76,r1_90,X_79); + (X_82,r1_97) := algebra.join(X_70,X_81); + X_84 := sql.bind(X_6,"sys","partsupp","ps_partkey",0); + (X_86,r1_101) := sql.bind(X_6,"sys","partsupp","ps_partkey",2); + X_88 := sql.bind(X_6,"sys","partsupp","ps_partkey",1); + X_89 := sql.projectdelta(X_71,X_84,X_86,r1_101,X_88); + X_90 := algebra.leftfetchjoin(r1_97,X_89); + (X_91,r1_107,r2_107) := group.subgroupdone(X_90); + X_94 := algebra.leftfetchjoin(r1_107,X_90); + X_109 := sql.bind(X_6,"sys","partsupp","ps_supplycost",0); + (X_112,r1_130) := sql.bind(X_6,"sys","partsupp","ps_supplycost",2); + X_115 := sql.bind(X_6,"sys","partsupp","ps_supplycost",1); + X_117 := sql.projectdelta(X_71,X_109,X_112,r1_130,X_115); + X_119 := algebra.leftfetchjoin(r1_97,X_117); + X_120:bat[:oid,:lng] := aggr.submin(X_119,X_91,r1_107,true); + (X_95,r1_111) := algebra.join(X_32,X_94); + X_97 := X_26; + X_98 := algebra.leftfetchjoin(X_95,X_97); + X_100 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_partkey_fkey",0); + (X_102,r1_119) := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_partkey_fkey",2); + X_105 := sql.bind_idxbat(X_6,"sys","partsupp","partsupp_ps_partkey_fkey",1); + X_106 := sql.projectdelta(X_71,X_100,X_102,r1_119,X_105); + (X_107,r1_125) := algebra.join(X_98,X_106); + X_118 := algebra.leftfetchjoin(r1_125,X_117); + X_122:bat[:oid,:lng] := algebra.leftfetchjoinPath(X_107,r1_111,X_120); + X_123:bat[:oid,:bit] := batcalc.==(X_118,X_122); + X_124 := algebra.subselect(X_123,true,true,true,true,false); + X_127:bat[:oid,:oid] := algebra.leftfetchjoinPath(X_124,r1_125,X_81); + (X_128,r1_167) := algebra.join(X_127,X_59); + X_133 := algebra.leftfetchjoin(r1_167,X_67); + X_134:bat[:oid,:oid] := sql.tid(X_6,"sys","nation"); + (X_136,r1_182) := algebra.join(X_133,X_134); + X_138 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",0); + (X_140,r1_186) := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",2); + X_142 := sql.bind_idxbat(X_6,"sys","nation","nation_n_regionkey_fkey",1); + X_144 := sql.projectdelta(X_134,X_138,X_140,r1_186,X_142); + X_145 := algebra.leftfetchjoin(r1_182,X_144); + X_148 := sql.bind(X_6,"sys","region","r_name",0); + X_146:bat[:oid,:oid] := sql.tid(X_6,"sys","region"); + X_343 := algebra.subselect(X_148,X_146,A2,A2,true,true,false); + (X_150,r1_197) := sql.bind(X_6,"sys","region","r_name",2); + X_344 := algebra.subselect(r1_197,A2,A2,true,true,false); + X_152 := sql.bind(X_6,"sys","region","r_name",1); + X_345 := algebra.subselect(X_152,X_146,A2,A2,true,true,false); + X_153 := sql.subdelta(X_343,X_146,X_150,X_344,X_345); + X_156 := X_153; + (X_157,r1_207) := algebra.join(X_145,X_156); + X_346 := algebra.leftfetchjoin(X_157,X_136); + X_159 := algebra.leftfetchjoin(X_124,X_107); + X_160:bat[:oid,:int] := algebra.leftfetchjoinPath(X_346,X_128,X_159,X_95,X_32); X_161 := sql.bind(X_6,"sys","supplier","s_name",0); - (X_166,r1_227) := sql.bind(X_6,"sys","supplier","s_name",2); - X_169 := sql.bind(X_6,"sys","supplier","s_name",1); - X_171 := sql.projectdelta(X_32,X_161,X_166,r1_227,X_169); - X_172:bat[:oid,:str] := algebra.leftfetchjoinPath(X_351,r1_177,X_125,X_101,r1_122,X_171); + (X_165,r1_219) := sql.bind(X_6,"sys","supplier","s_name",2); + X_168 := sql.bind(X_6,"sys","supplier","s_name",1); + X_171 := sql.projectdelta(X_59,X_161,X_165,r1_219,X_168); + X_172:bat[:oid,:str] := algebra.leftfetchjoinPath(X_346,r1_167,X_171); X_173 := sql.bind(X_6,"sys","nation","n_name",0); - (X_176,r1_243) := sql.bind(X_6,"sys","nation","n_name",2); + (X_176,r1_233) := sql.bind(X_6,"sys","nation","n_name",2); X_178 := sql.bind(X_6,"sys","nation","n_name",1); - X_179 := sql.projectdelta(X_99,X_173,X_176,r1_243,X_178); - X_180:bat[:oid,:str] := algebra.leftfetchjoinPath(X_351,r1_177,X_125,r1_134,X_179); + X_179 := sql.projectdelta(X_134,X_173,X_176,r1_233,X_178); + X_180:bat[:oid,:str] := algebra.leftfetchjoinPath(X_157,r1_182,X_179); X_181 := sql.bind(X_6,"sys","supplier","s_acctbal",0); - (X_183,r1_255) := sql.bind(X_6,"sys","supplier","s_acctbal",2); - X_187 := sql.bind(X_6,"sys","supplier","s_acctbal",1); - X_188 := sql.projectdelta(X_32,X_181,X_183,r1_255,X_187); - X_189:bat[:oid,:lng] := algebra.leftfetchjoinPath(X_351,r1_177,X_125,X_101,r1_122,X_188); - (X_190,r1_273) := algebra.firstn(X_189,100:wrd,false,false); - (X_193,r1_278) := algebra.firstn(X_180,X_190,r1_273,100:wrd,true,false); - (X_196,r1_283) := algebra.firstn(X_172,X_193,r1_278,100:wrd,true,false); - X_198 := algebra.firstn(X_160,X_196,r1_283,100:wrd,true,false); - X_223 := sql.bind(X_6,"sys","part","p_mfgr",0); - (X_228,r1_325) := sql.bind(X_6,"sys","part","p_mfgr",2); - X_231 := sql.bind(X_6,"sys","part","p_mfgr",1); - X_232 := sql.projectdelta(X_90,X_223,X_228,r1_325,X_231); - X_199 := algebra.leftfetchjoin(X_198,X_160); - X_200 := algebra.leftfetchjoin(X_198,X_172); - X_201 := algebra.leftfetchjoin(X_198,X_180); - X_202 := algebra.leftfetchjoin(X_198,X_189); - (X_203,r1_292,r2_292) := algebra.subsort(X_202,true,false); - (X_206,r1_295,r2_295) := algebra.subsort(X_201,r1_292,r2_292,false,false); - (X_209,r1_298,r2_298) := algebra.subsort(X_200,r1_295,r2_295,false,false); - (X_212,r1_301,r2_301) := algebra.subsort(X_199,r1_298,r2_298,false,false); - X_215 := algebra.leftfetchjoin(r1_301,X_202); - X_218 := algebra.subslice(X_215,0:wrd,99:wrd); - X_352 := algebra.leftfetchjoin(X_218,r1_301); - X_233:bat[:oid,:str] := algebra.leftfetchjoinPath(X_352,X_198,X_158,r1_183,r1_177,X_125,X_101,X_96,r1_108,X_232); - X_234 := sql.bind(X_6,"sys","supplier","s_address",0); - (X_237,r1_345) := sql.bind(X_6,"sys","supplier","s_address",2); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list