Changeset: 003d63f8443d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/003d63f8443d
Modified Files:
        clients/Tests/MAL-signatures.stable.out
        clients/Tests/MAL-signatures.stable.out.int128
        monetdb5/modules/mal/wlc.c
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
        sql/backends/monet5/wlr.c
Branch: Jan2022
Log Message:

Truncate statements may restart sequences. If so, do it on the backend and not 
while generating backend code


diffs (truncated from 481 to 300 lines):

diff --git a/clients/Tests/MAL-signatures.stable.out 
b/clients/Tests/MAL-signatures.stable.out
--- a/clients/Tests/MAL-signatures.stable.out
+++ b/clients/Tests/MAL-signatures.stable.out
@@ -9293,7 +9293,7 @@
 [ "sql",       "bind_idxbat",  "pattern sql.bind_idxbat(X_0:int, X_1:str, 
X_2:str, X_3:str, X_4:int, X_5:int, X_6:int) (X_7:bat[:oid], X_8:bat[:any_1]) 
",     "mvc_bind_idxbat_wrap;",        "Bind the 'schema.table.index' BAT with 
access kind:\n0 - base table\n1 - inserts\n2 - updates" ]
 [ "sql",       "bind_idxbat",  "pattern sql.bind_idxbat(X_0:int, X_1:str, 
X_2:str, X_3:str, X_4:int, X_5:int, X_6:int):bat[:any_1] ",  
"mvc_bind_idxbat_wrap;",        "Bind the 'schema.table.index' BAT with access 
kind:\n0 - base table\n1 - inserts\n2 - updates" ]
 [ "sql",       "claim",        "unsafe pattern sql.claim(X_0:int, X_1:str, 
X_2:str, X_3:lng) (X_4:oid, X_5:bat[:oid]) ",       "mvc_claim_wrap;",      
"Claims slots for appending rows."      ]
-[ "sql",       "clear_table",  "unsafe pattern sql.clear_table(X_0:str, 
X_1:str):lng ",        "mvc_clear_table_wrap;",        "Clear the table 
sname.tname."  ]
+[ "sql",       "clear_table",  "unsafe pattern sql.clear_table(X_0:str, 
X_1:str, X_2:int):lng ",       "mvc_clear_table_wrap;",        "Clear the table 
sname.tname."  ]
 [ "sql",       "copy_from",    "unsafe pattern sql.copy_from(X_0:ptr, X_1:str, 
X_2:str, X_3:str, X_4:str, X_5:str, X_6:lng, X_7:lng, X_8:int, X_9:str, 
X_10:int, X_11:int):bat[:any]... ",     "mvc_import_table_wrap;",       "Import 
a table from bstream s with the \ngiven tuple and seperators (sep/rsep)"        
]
 [ "sql",       "copy_rejects", "pattern sql.copy_rejects() (X_0:bat[:lng], 
X_1:bat[:int], X_2:bat[:str], X_3:bat[:str]) ",     "COPYrejects;", ""      ]
 [ "sql",       "copy_rejects_clear",   "unsafe pattern 
sql.copy_rejects_clear():void ",        "COPYrejects_clear;",   ""      ]
@@ -9680,7 +9680,7 @@
 [ "wlc",       "alter_user",   "pattern wlc.alter_user(X_0:str, X_1:str, 
X_2:int, X_3:str, X_4:str):void ",    "WLCgeneric;",  "Catalog operation 
alter_user"  ]
 [ "wlc",       "append",       "pattern wlc.append(X_0:str, X_1:str, X_2:str, 
X_3:any):int ",  "WLCappend;",   "Keep the insertions in the 
workload-capture-replay list"       ]
 [ "wlc",       "catalog",      "pattern wlc.catalog(X_0:str):void ",   
"WLCcatalog;",  "Keep the catalog changing queries for replay. "        ]
-[ "wlc",       "clear_table",  "pattern wlc.clear_table(X_0:str, X_1:str):int 
",       "WLCclear_table;",      "Keep the deletions in the 
workload-capture-replay list"        ]
+[ "wlc",       "clear_table",  "pattern wlc.clear_table(X_0:str, X_1:str, 
X_2:int):int ",      "WLCclear_table;",      "Keep the deletions in the 
workload-capture-replay list"        ]
 [ "wlc",       "comment_on",   "pattern wlc.comment_on(X_0:int, X_1:str):void 
",       "WLCgeneric;",  "Catalog operation comment_on"  ]
 [ "wlc",       "commit",       "pattern wlc.commit():void ",   
"WLCcommitCmd;",        "Commit the workload-capture-replay record"     ]
 [ "wlc",       "commit",       "pattern wlc.commit():void ",   
"WLCcommitCmd;",        "Mark the end of the work unit" ]
@@ -9750,7 +9750,7 @@
 [ "wlr",       "alter_user",   "pattern wlr.alter_user(X_0:str, X_1:str, 
X_2:int, X_3:str, X_4:str):void ",    "WLRgeneric;",  "Catalog operation 
alter_user"  ]
 [ "wlr",       "append",       "pattern wlr.append(X_0:str, X_1:str, X_2:str, 
X_3:oid, X_4:bat[:oid], X_5:any...):int ",       "WLRappend;",   "Apply the 
insertions in the workload-capture-replay list"      ]
 [ "wlr",       "catalog",      "pattern wlr.catalog(X_0:str):void ",   
"WLRcatalog;",  "A catalog changing query"      ]
-[ "wlr",       "clear_table",  "pattern wlr.clear_table(X_0:str, X_1:str):int 
",       "WLRclear_table;",      "Destroy the tuples in the table"       ]
+[ "wlr",       "clear_table",  "pattern wlr.clear_table(X_0:str, X_1:str, 
X_2:int):int ",      "WLRclear_table;",      "Destroy the tuples in the table"  
     ]
 [ "wlr",       "comment_on",   "pattern wlr.comment_on(X_0:int, X_1:str):void 
",       "WLRgeneric;",  "Catalog operation comment_on"  ]
 [ "wlr",       "commit",       "pattern wlr.commit():void ",   "WLRcommit;",   
"Mark the end of the work unit" ]
 [ "wlr",       "create_function",      "pattern wlr.create_function(X_0:str, 
X_1:str, X_2:int):void ", "WLRgeneric;",  "Catalog operation create_function"   
  ]
diff --git a/clients/Tests/MAL-signatures.stable.out.int128 
b/clients/Tests/MAL-signatures.stable.out.int128
--- a/clients/Tests/MAL-signatures.stable.out.int128
+++ b/clients/Tests/MAL-signatures.stable.out.int128
@@ -12595,7 +12595,7 @@
 [ "sql",       "bind_idxbat",  "pattern sql.bind_idxbat(X_0:int, X_1:str, 
X_2:str, X_3:str, X_4:int, X_5:int, X_6:int) (X_7:bat[:oid], X_8:bat[:any_1]) 
",     "mvc_bind_idxbat_wrap;",        "Bind the 'schema.table.index' BAT with 
access kind:\n0 - base table\n1 - inserts\n2 - updates" ]
 [ "sql",       "bind_idxbat",  "pattern sql.bind_idxbat(X_0:int, X_1:str, 
X_2:str, X_3:str, X_4:int, X_5:int, X_6:int):bat[:any_1] ",  
"mvc_bind_idxbat_wrap;",        "Bind the 'schema.table.index' BAT with access 
kind:\n0 - base table\n1 - inserts\n2 - updates" ]
 [ "sql",       "claim",        "unsafe pattern sql.claim(X_0:int, X_1:str, 
X_2:str, X_3:lng) (X_4:oid, X_5:bat[:oid]) ",       "mvc_claim_wrap;",      
"Claims slots for appending rows."      ]
-[ "sql",       "clear_table",  "unsafe pattern sql.clear_table(X_0:str, 
X_1:str):lng ",        "mvc_clear_table_wrap;",        "Clear the table 
sname.tname."  ]
+[ "sql",       "clear_table",  "unsafe pattern sql.clear_table(X_0:str, 
X_1:str, X_2:int):lng ",       "mvc_clear_table_wrap;",        "Clear the table 
sname.tname."  ]
 [ "sql",       "copy_from",    "unsafe pattern sql.copy_from(X_0:ptr, X_1:str, 
X_2:str, X_3:str, X_4:str, X_5:str, X_6:lng, X_7:lng, X_8:int, X_9:str, 
X_10:int, X_11:int):bat[:any]... ",     "mvc_import_table_wrap;",       "Import 
a table from bstream s with the \ngiven tuple and seperators (sep/rsep)"        
]
 [ "sql",       "copy_rejects", "pattern sql.copy_rejects() (X_0:bat[:lng], 
X_1:bat[:int], X_2:bat[:str], X_3:bat[:str]) ",     "COPYrejects;", ""      ]
 [ "sql",       "copy_rejects_clear",   "unsafe pattern 
sql.copy_rejects_clear():void ",        "COPYrejects_clear;",   ""      ]
@@ -13001,7 +13001,7 @@
 [ "wlc",       "alter_user",   "pattern wlc.alter_user(X_0:str, X_1:str, 
X_2:int, X_3:str, X_4:str):void ",    "WLCgeneric;",  "Catalog operation 
alter_user"  ]
 [ "wlc",       "append",       "pattern wlc.append(X_0:str, X_1:str, X_2:str, 
X_3:any):int ",  "WLCappend;",   "Keep the insertions in the 
workload-capture-replay list"       ]
 [ "wlc",       "catalog",      "pattern wlc.catalog(X_0:str):void ",   
"WLCcatalog;",  "Keep the catalog changing queries for replay. "        ]
-[ "wlc",       "clear_table",  "pattern wlc.clear_table(X_0:str, X_1:str):int 
",       "WLCclear_table;",      "Keep the deletions in the 
workload-capture-replay list"        ]
+[ "wlc",       "clear_table",  "pattern wlc.clear_table(X_0:str, X_1:str, 
X_2:int):int ",      "WLCclear_table;",      "Keep the deletions in the 
workload-capture-replay list"        ]
 [ "wlc",       "comment_on",   "pattern wlc.comment_on(X_0:int, X_1:str):void 
",       "WLCgeneric;",  "Catalog operation comment_on"  ]
 [ "wlc",       "commit",       "pattern wlc.commit():void ",   
"WLCcommitCmd;",        "Commit the workload-capture-replay record"     ]
 [ "wlc",       "commit",       "pattern wlc.commit():void ",   
"WLCcommitCmd;",        "Mark the end of the work unit" ]
@@ -13071,7 +13071,7 @@
 [ "wlr",       "alter_user",   "pattern wlr.alter_user(X_0:str, X_1:str, 
X_2:int, X_3:str, X_4:str):void ",    "WLRgeneric;",  "Catalog operation 
alter_user"  ]
 [ "wlr",       "append",       "pattern wlr.append(X_0:str, X_1:str, X_2:str, 
X_3:oid, X_4:bat[:oid], X_5:any...):int ",       "WLRappend;",   "Apply the 
insertions in the workload-capture-replay list"      ]
 [ "wlr",       "catalog",      "pattern wlr.catalog(X_0:str):void ",   
"WLRcatalog;",  "A catalog changing query"      ]
-[ "wlr",       "clear_table",  "pattern wlr.clear_table(X_0:str, X_1:str):int 
",       "WLRclear_table;",      "Destroy the tuples in the table"       ]
+[ "wlr",       "clear_table",  "pattern wlr.clear_table(X_0:str, X_1:str, 
X_2:int):int ",      "WLRclear_table;",      "Destroy the tuples in the table"  
     ]
 [ "wlr",       "comment_on",   "pattern wlr.comment_on(X_0:int, X_1:str):void 
",       "WLRgeneric;",  "Catalog operation comment_on"  ]
 [ "wlr",       "commit",       "pattern wlr.commit():void ",   "WLRcommit;",   
"Mark the end of the work unit" ]
 [ "wlr",       "create_function",      "pattern wlr.create_function(X_0:str, 
X_1:str, X_2:int):void ", "WLRgeneric;",  "Catalog operation create_function"   
  ]
diff --git a/monetdb5/modules/mal/wlc.c b/monetdb5/modules/mal/wlc.c
--- a/monetdb5/modules/mal/wlc.c
+++ b/monetdb5/modules/mal/wlc.c
@@ -1014,6 +1014,7 @@ WLCclear_table(Client cntxt, MalBlkPtr m
        p = newStmt(cntxt->wlc, "wlr","clear_table");
        p = pushStr(cntxt->wlc, p, getVarConstant(mb, getArg(pci,1)).val.sval);
        p = pushStr(cntxt->wlc, p, getVarConstant(mb, getArg(pci,2)).val.sval);
+       p = pushInt(cntxt->wlc, p, getVarConstant(mb, getArg(pci,3)).val.ival);
        if( cntxt->wlc_kind < WLC_UPDATE)
                cntxt->wlc_kind = WLC_UPDATE;
 
@@ -1086,7 +1087,7 @@ mel_func wlc_init_funcs[] = {
  pattern("wlc", "append", WLCappend, false, "Keep the insertions in the 
workload-capture-replay list", args(1,5, 
arg("",int),arg("sname",str),arg("tname",str),arg("cname",str),argany("ins",0))),
  pattern("wlc", "update", WLCupdate, false, "Keep the update in the 
workload-capture-replay list", args(1,6, 
arg("",int),arg("sname",str),arg("tname",str),arg("cname",str),argany("tid",0),argany("val",0))),
  pattern("wlc", "delete", WLCdelete, false, "Keep the deletions in the 
workload-capture-replay list", args(1,4, 
arg("",int),arg("sname",str),arg("tname",str),argany("b",0))),
- pattern("wlc", "clear_table", WLCclear_table, false, "Keep the deletions in 
the workload-capture-replay list", args(1,3, 
arg("",int),arg("sname",str),arg("tname",str))),
+ pattern("wlc", "clear_table", WLCclear_table, false, "Keep the deletions in 
the workload-capture-replay list", args(1,4, 
arg("",int),arg("sname",str),arg("tname",str),arg("restart_sequences",int))),
  pattern("wlc", "commit", WLCcommitCmd, false, "Commit the 
workload-capture-replay record", noargs),
  pattern("wlc", "rollback", WLCcommitCmd, false, "Rollback the 
workload-capture-replay record", noargs),
  pattern("wlc", "create_seq", WLCgeneric, false, "Catalog operation 
create_seq", args(0,3, arg("sname",str),arg("seqname",str),arg("action",int))),
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
@@ -5203,7 +5203,7 @@ sql_update(backend *be, sql_table *t, st
                sql_column *c = n->data;
 
                if (updates[i])
-                       append(l, stmt_update_col(be, c, rows, updates[i]));
+                       append(l, stmt_update_col(be, c, rows, updates[i]));
        }
        if (cascade_updates(be, t, rows, updates))
                return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade 
failed for table '%s'", t->base.name);
@@ -5541,7 +5541,7 @@ sql_delete(backend *be, sql_table *t, st
                if (!be->silent)
                        s = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(sql, 
"sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
        } else { /* delete all */
-               s = stmt_table_clear(be, t); /* first column */
+               s = stmt_table_clear(be, t, 0); /* first column */
        }
 
 /* after */
@@ -5594,34 +5594,26 @@ struct tablelist {
        struct tablelist* next;
 };
 
-static void /* inspect the other tables recursively for foreign key 
dependencies */
-check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct 
tablelist* next_append, sql_table *t, int cascade, int *error)
+static sql_table * /* inspect the other tables recursively for foreign key 
dependencies */
+check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct 
tablelist* next_append, sql_table *t, int cascade)
 {
-       node *n;
-       int found;
-       struct tablelist* new_node, *node_check;
+       struct tablelist* new_node;
        sql_trans *tr = sql->session->tr;
-
-       if (THRhighwater()) {
-               sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running 
out of stack space");
-               *error = 1;
-               return;
-       }
-
-       if (*error)
-               return;
-
        sqlstore *store = sql->session->tr->store;
+
+       if (THRhighwater())
+               return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: 
running out of stack space");
+
        if (t->keys) { /* Check for foreign key references */
-               for (n = ol_first_node(t->keys); n; n = n->next) {
+               for (node *n = ol_first_node(t->keys); n; n = n->next) {
                        sql_key *k = n->data;
 
                        if (k->type == ukey || k->type == pkey) {
                                list *keys = sql_trans_get_dependencies(tr, 
k->base.id, FKEY_DEPENDENCY, NULL);
 
                                if (keys) {
-                                       for (node *n = keys->h; n; n = 
n->next->next) {
-                                               sqlid fkey_id = 
*(sqlid*)n->data;
+                                       for (node *nn = keys->h; nn; nn = 
nn->next->next) {
+                                               sqlid fkey_id = 
*(sqlid*)nn->data;
                                                sql_base *b = 
os_find_id(tr->cat->objects, tr, fkey_id);
                                                sql_key *fk = (sql_key*)b;
                                                sql_fkey *rk = (sql_fkey*)b;
@@ -5631,32 +5623,31 @@ check_for_foreign_key_references(mvc *sq
                                                k = fk;
                                                /* make sure it is not a self 
referencing key */
                                                if (k->t != t && !cascade && 
isTable(t)) {
-                                                       node *n = 
ol_first_node(t->columns);
-                                                       sql_column *c = n->data;
+                                                       node *nnn = 
ol_first_node(t->columns);
+                                                       sql_column *c = 
nnn->data;
                                                        size_t n_rows = 
store->storage_api.count_col(sql->session->tr, c, 10);
                                                        if (n_rows > 0) {
                                                                
list_destroy(keys);
-                                                               sql_error(sql, 
02, SQLSTATE(23000) "TRUNCATE: FOREIGN KEY %s.%s depends on %s", 
k->t->base.name, k->base.name, t->base.name);
-                                                               *error = 1;
-                                                               return;
+                                                               return 
sql_error(sql, 02, SQLSTATE(23000) "TRUNCATE: FOREIGN KEY %s.%s depends on %s", 
k->t->base.name, k->base.name, t->base.name);
                                                        }
                                                } else if (k->t != t) {
-                                                       found = 0;
-                                                       for (node_check = 
tlist; node_check; node_check = node_check->next) {
+                                                       int found = 0;
+                                                       for (struct tablelist 
*node_check = tlist; node_check; node_check = node_check->next) {
                                                                if 
(node_check->table == k->t)
                                                                        found = 
1;
                                                        }
                                                        if (!found) {
                                                                if ((new_node = 
SA_NEW(sql->ta, struct tablelist)) == NULL) {
                                                                        
list_destroy(keys);
-                                                                       
sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-                                                                       *error 
= 1;
-                                                                       return;
+                                                                       return 
sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
                                                                }
                                                                new_node->table 
= k->t;
                                                                new_node->next 
= NULL;
                                                                
next_append->next = new_node;
-                                                               
check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade, error);
+                                                               if 
(!check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade)) {
+                                                                       
list_destroy(keys);
+                                                                       return 
NULL;
+                                                               }
                                                        }
                                                }
                                        }
@@ -5665,6 +5656,7 @@ check_for_foreign_key_references(mvc *sq
                        }
                }
        }
+       return t;
 }
 
 static stmt *
@@ -5672,72 +5664,22 @@ sql_truncate(backend *be, sql_table *t, 
 {
        mvc *sql = be->mvc;
        list *l = sa_list(sql->sa);
-       stmt *v, *ret = NULL, *other = NULL;
-       const char *next_value_for = "next value for ";
-       sql_column *col = NULL;
-       sql_schema *sche = NULL;
-       sql_table *next = NULL;
-       sql_trans *tr = sql->session->tr;
-       int error = 0;
-       struct tablelist* new_list = SA_NEW(sql->ta, struct tablelist), 
*list_node;
+       stmt *ret = NULL, *other = NULL;
+       struct tablelist *new_list = SA_NEW(sql->ta, struct tablelist);
        stmt **deleted_cols = NULL;
 
-       if (!new_list) {
-               sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-               error = 1;
-               goto finalize;
-       }
-
+       if (!new_list)
+               return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
        new_list->table = t;
        new_list->next = NULL;
-       check_for_foreign_key_references(sql, new_list, new_list, t, cascade, 
&error);
-       if (error)
+       if (!check_for_foreign_key_references(sql, new_list, new_list, t, 
cascade))
                goto finalize;
 
-       for (list_node = new_list; list_node; list_node = list_node->next) {
-               next = list_node->table;
-               sche = next->s;
-
-               if (restart_sequences) { /* restart the sequences if it's the 
case */
-                       for (node *n = ol_first_node(next->columns); n; n = 
n->next) {
-                               col = n->data;
-
-                               if (col->def && !strncmp(col->def, 
next_value_for, strlen(next_value_for))) {
-                                       sql_schema *s = NULL;
-                                       sql_sequence *seq = NULL;
-                                       char *schema = NULL, *seq_name = NULL;
-
-                                       
extract_schema_and_sequence_name(sql->ta, col->def + strlen(next_value_for), 
&schema, &seq_name);
-                                       if (!schema || !seq_name || !(s = 
find_sql_schema(tr, schema)))
-                                               continue;
-
-                                       assert(s->base.id == sche->base.id);
-                                       if ((seq = find_sql_sequence(tr, s, 
seq_name))) {
-                                               switch 
(sql_trans_sequence_restart(tr, seq, seq->start)) {
-                                                       case -1:
-                                                               sql_error(sql, 
10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
-                                                               error = 1;
-                                                               goto finalize;
-                                                       case -2:
-                                                       case -3:
-                                                               sql_error(sql, 
02, SQLSTATE(HY005) "RESTART SEQUENCE: transaction conflict detected");
-                                                               error = 1;
-                                                               goto finalize;
-                                                       case -4:
-                                                               sql_error(sql, 
02, SQLSTATE(HY005) "Could not restart sequence %s.%s", sche->base.name, 
seq_name);
-                                                               error = 1;
-                                                               goto finalize;
-                                                       default:
-                                                               break;
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               v = stmt_tid(be, next, 0);
-
-               /*  project all columns */
+       for (struct tablelist *list_node = new_list; list_node; list_node = 
list_node->next) {
+               sql_table *next = list_node->table;
+               stmt *v = stmt_tid(be, next, 0);
+
+               /* project all columns */
                if (ol_length(t->triggers) || 
partition_find_part(sql->session->tr, t, NULL)) {
                        int nr = 0;
                        deleted_cols = table_update_stmts(sql, t, &nr);
@@ -5753,26 +5695,26 @@ sql_truncate(backend *be, sql_table *t, 
 
                /* before */
                if (!sql_delete_triggers(be, next, v, deleted_cols, 0, 3, 4)) {
-                       sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers 
failed for table '%s'", next->base.name);
-                       error = 1;
+                       (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: 
triggers failed for table '%s'", next->base.name);
+                       ret = NULL;
                        goto finalize;
                }
 
                if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
-                       sql_error(sql, 10, SQLSTATE(42000) "TRUNCATE: failed to 
delete indexes for table '%s'", next->base.name);
-                       error = 1;
+                       (void) sql_error(sql, 10, SQLSTATE(42000) "TRUNCATE: 
failed to delete indexes for table '%s'", next->base.name);
+                       ret = NULL;
                        goto finalize;
                }
 
-               other = stmt_table_clear(be, next);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to