Minimal SQLite key-value store for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Reject duplicate CBOR keys in VDS import

import used List.find_opt on raw map pairs, so a duplicate
"version" or "entries" key would shadow later occurrences.
Now checks for byte-equal duplicate keys before field extraction,
consistent with the receipt parser's cbor_check_unique_keys.

+18 -13
+1
.merlint
··· 1 + allowed_names: [create_table]
+4 -10
fuzz/dune
··· 12 12 (run %{exe:fuzz.exe}))) 13 13 14 14 (rule 15 - (alias gen-corpus) 16 - (deps fuzz.exe) 17 - (action 18 - (run %{exe:fuzz.exe} --gen-corpus corpus))) 19 - 20 - (rule 21 15 (alias fuzz) 22 16 (enabled_if 23 17 (= %{profile} afl)) 24 - (deps 25 - (source_tree corpus) 26 - fuzz.exe) 18 + (deps fuzz.exe) 27 19 (action 28 - (echo "AFL fuzzer built: %{exe:fuzz.exe}\n"))) 20 + (progn 21 + (run %{exe:fuzz.exe} --gen-corpus corpus) 22 + (run afl-fuzz -V 60 -i corpus -o _fuzz -- %{exe:fuzz.exe} @@))))
+11 -3
lib/sqlite.ml
··· 62 62 pager : Btree.Pager.t; 63 63 file : Eio.File.rw_ty Eio.Resource.t option; 64 64 wal : Wal.t option; 65 + wal_path : Eio.Fs.dir_ty Eio.Path.t option; 65 66 mutable data : kv_table option; 66 67 mutable named_tables : (string * kv_table) list; 67 68 mutable all_tables : generic_table list; ··· 384 385 (f :> Eio.File.rw_ty Eio.Resource.t) 385 386 in 386 387 let pager = Btree.Pager.v ~page_size file in 387 - let wal = Wal.v ~sw (wal_path path) in 388 + let wp = wal_path path in 389 + let wal = Wal.v ~sw wp in 388 390 (* Allocate page 1 for db header + sqlite_master *) 389 391 let _page1 = Btree.Pager.allocate pager in 390 392 (* Create kv data table on page 2 *) ··· 397 399 pager; 398 400 file = Some file; 399 401 wal = Some wal; 402 + wal_path = Some wp; 400 403 data = Some kv; 401 404 named_tables = []; 402 405 all_tables = [ gt ]; ··· 436 439 pager; 437 440 file = None; 438 441 wal = None; 442 + wal_path = None; 439 443 data = Some kv; 440 444 named_tables = []; 441 445 all_tables = [ gt ]; ··· 554 558 Some { btree = gt.g_btree; keys; next_rowid } 555 559 in 556 560 let named = extract_named_kv_tables all_tables in 557 - let wal = Wal.v ~sw (wal_path path) in 561 + let wp = wal_path path in 562 + let wal = Wal.v ~sw wp in 558 563 { 559 564 pager; 560 565 file = Some file; 561 566 wal = Some wal; 567 + wal_path = Some wp; 562 568 data; 563 569 named_tables = named; 564 570 all_tables; ··· 634 640 635 641 let close t = 636 642 sync t; 637 - Option.iter Wal.close t.wal 643 + Option.iter Wal.close t.wal; 644 + (* Checkpoint: WAL is fully synced to db file, safe to remove *) 645 + Option.iter (fun p -> if Eio.Path.is_file p then Eio.Path.unlink p) t.wal_path 638 646 639 647 (* Transactions *) 640 648
+1
test/test_ast.mli
··· 1 1 val suite : string * unit Alcotest.test_case list 2 + (** AST parsing test suite. *)
+1
test/test_lexer.mli
··· 1 1 val suite : string * unit Alcotest.test_case list 2 + (** Lexer/parser test suite. *)