From 5487e6073820bb673407155b30560551271df0e0 Mon Sep 17 00:00:00 2001 From: Ilja Heitlager Date: Thu, 27 Aug 2026 22:40:09 +0200 Subject: [PATCH 1/3] fix: update btree_cursor fuzz target to Rc<[u8]> PageSource signature PageSource::read_page returns Rc<[u8]> to share page buffers instead of copying, but the fuzz target's FuzzPageSource impl still returned Vec, breaking `make fuzz-btree`. Co-Authored-By: Claude Sonnet 5 --- tests/fuzz/Cargo.lock | 85 +------------------------ tests/fuzz/fuzz_targets/btree_cursor.rs | 6 +- 2 files changed, 5 insertions(+), 86 deletions(-) diff --git a/tests/fuzz/Cargo.lock b/tests/fuzz/Cargo.lock index a9edd675..0b143979 100644 --- a/tests/fuzz/Cargo.lock +++ b/tests/fuzz/Cargo.lock @@ -8,12 +8,6 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" -[[package]] -name = "bitflags" -version = "2.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" - [[package]] name = "cc" version = "1.4.3" @@ -32,12 +26,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" - [[package]] name = "find-msvc-tools" version = "0.1.11" @@ -81,36 +69,6 @@ dependencies = [ "cc", ] -[[package]] -name = "nix" -version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "proc-macro2" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" -dependencies = [ - "proc-macro2", -] - [[package]] name = "r-efi" version = "6.0.0" @@ -125,11 +83,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "sqlite-rs" -version = "0.7.0" -dependencies = [ - "nix", - "thiserror", -] +version = "0.18.5" [[package]] name = "sqlite-rs-fuzz" @@ -138,40 +92,3 @@ dependencies = [ "libfuzzer-sys", "sqlite-rs", ] - -[[package]] -name = "syn" -version = "2.0.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/tests/fuzz/fuzz_targets/btree_cursor.rs b/tests/fuzz/fuzz_targets/btree_cursor.rs index f161b428..b40ab003 100644 --- a/tests/fuzz/fuzz_targets/btree_cursor.rs +++ b/tests/fuzz/fuzz_targets/btree_cursor.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 #![no_main] +use std::rc::Rc; + use libfuzzer_sys::fuzz_target; use sqlite_rs::btree::TableCursor; @@ -19,14 +21,14 @@ struct FuzzPageSource<'a> { } impl PageSource for FuzzPageSource<'_> { - fn read_page(&self, page_num: u32) -> Result, PageError> { + fn read_page(&self, page_num: u32) -> Result, PageError> { if page_num == 0 || page_num > 8 { return Err(PageError::InvalidPageNumber); } let mut buf = vec![0u8; self.page_size as usize]; let n = self.data.len().min(buf.len()); buf[..n].copy_from_slice(&self.data[..n]); - Ok(buf) + Ok(Rc::from(buf)) } } From a83529979b34edd426849153769432f53fadb7c5 Mon Sep 17 00:00:00 2001 From: Ilja Heitlager Date: Thu, 27 Aug 2026 22:46:56 +0200 Subject: [PATCH 2/3] chore: regenerate MC/DC obligations snapshot, rename shifted tagged tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tests/mcdc/obligations.json had drifted from source line numbers. Regenerated via `make mcdc-obligations` and renamed every mcdc____vN tagged test (and its doc-comment cross-references) to the id its decision now resolves to, so `unit_mcdc_discharge` and `cargo-mvl-mcdc harvest` join tagged tests to obligations correctly again. This also surfaces the true discharge state: 40/42 real MC/DC obligations are discharged (previously misreported near 0 due to the id drift) — btree_966 and encode_68 remain undischarged. Token spend: trivial, matched estimate (mechanical id rename, no new test logic). Co-Authored-By: Claude Sonnet 5 --- src/btree.rs | 16 +- src/btree/index.rs | 16 +- src/btree/table/delete.rs | 20 +- src/parser/grammar.rs | 286 ++--- src/parser/tokenizer.rs | 64 +- src/record/encode.rs | 16 +- src/vdbe/exec.rs | 32 +- src/vdbe/functions.rs | 230 ++-- tests/mcdc/obligations.json | 2365 +++++++++++++++++++---------------- 9 files changed, 1599 insertions(+), 1446 deletions(-) diff --git a/src/btree.rs b/src/btree.rs index da49d4c7..93b7b197 100644 --- a/src/btree.rs +++ b/src/btree.rs @@ -2330,7 +2330,7 @@ mod tests { assert!(!spliced, "no contiguous gap must decline the fast path"); } - /// #52 tagged MC/DC vector (obligation `btree_1296`, decision + /// #52 tagged MC/DC vector (obligation `btree_1374`, decision /// `content_start < ptr_end || content_start.saturating_sub(ptr_end) /// < needed`): leaf A (`content_start < ptr_end`) true independently /// flips the outcome to true regardless of leaf B — a corrupt/ @@ -2340,7 +2340,7 @@ mod tests { /// leaves false) for A's independence pair. #[test] #[allow(non_snake_case)] - fn mcdc__btree_1296__v1_content_start_before_ptr_end() { + fn mcdc__btree_1374__v1_content_start_before_ptr_end() { let mut buf = vec![0u8; 32]; put_u8(&mut buf, 0, LEAF_TABLE, 1).unwrap(); write_content_start(&mut buf, 0, 4, 1).unwrap(); // ptr_base(8) + 0 cells == 8 > content_start(4) @@ -2352,12 +2352,12 @@ mod tests { ); } - /// #52 tagged MC/DC vector (obligation `btree_1296`): both leaves + /// #52 tagged MC/DC vector (obligation `btree_1374`): both leaves /// false — the fast path proceeds. Independence pair for leaf A - /// against `mcdc__btree_1296__v1_content_start_before_ptr_end`. + /// against `mcdc__btree_1374__v1_content_start_before_ptr_end`. #[test] #[allow(non_snake_case)] - fn mcdc__btree_1296__v2_both_leaves_false() { + fn mcdc__btree_1374__v2_both_leaves_false() { let mut buf = leaf_page_with_cells(512, &[]); let cell = build_interior_cell(0, 42); let spliced = splice_insert_cell(&mut buf, 0, 1, 0, &cell).unwrap(); @@ -2367,14 +2367,14 @@ mod tests { ); } - /// #52 tagged MC/DC vector (obligation `btree_1296`): leaf B + /// #52 tagged MC/DC vector (obligation `btree_1374`): leaf B /// (`content_start.saturating_sub(ptr_end) < needed`) true while A is /// false independently flips the outcome to true — a zero-size gap. /// Independence pair for leaf B against - /// `mcdc__btree_1296__v2_both_leaves_false`. + /// `mcdc__btree_1374__v2_both_leaves_false`. #[test] #[allow(non_snake_case)] - fn mcdc__btree_1296__v3_gap_too_small() { + fn mcdc__btree_1374__v3_gap_too_small() { let mut buf = vec![0u8; 32]; put_u8(&mut buf, 0, LEAF_TABLE, 1).unwrap(); write_content_start(&mut buf, 0, 8, 1).unwrap(); // ptr_base(8) + 0 cells == 8, zero gap diff --git a/src/btree/index.rs b/src/btree/index.rs index e4213a3d..994ac216 100644 --- a/src/btree/index.rs +++ b/src/btree/index.rs @@ -799,39 +799,39 @@ mod tests { assert_eq!(int(&key[1]), 100); } - /// #52 tagged MC/DC vector (obligation `index_864`, the ordering-check + /// #52 tagged MC/DC vector (obligation `index_868`, the ordering-check /// decision `idx < expect_order.len() && text(&key[0]) == expect_order[idx]` /// inside `without_rowid_table_is_readable_as_index_btree` below): both /// leaves true. #[test] #[allow(non_snake_case)] - fn mcdc__index_864__v1_in_range_and_matches() { + fn mcdc__index_868__v1_in_range_and_matches() { let expect_order = ["key1"]; let idx = 0; let key0 = "key1"; assert!(idx < expect_order.len() && key0 == expect_order[idx]); } - /// #52 tagged MC/DC vector (obligation `index_864`): leaf A + /// #52 tagged MC/DC vector (obligation `index_868`): leaf A /// (`idx < expect_order.len()`) true, leaf B (key match) false — /// independence pair for B against - /// `mcdc__index_864__v1_in_range_and_matches`. + /// `mcdc__index_868__v1_in_range_and_matches`. #[test] #[allow(non_snake_case)] - fn mcdc__index_864__v2_in_range_but_does_not_match() { + fn mcdc__index_868__v2_in_range_but_does_not_match() { let expect_order = ["key1"]; let idx = 0; let key0 = "key2"; assert!(!(idx < expect_order.len() && key0 == expect_order[idx])); } - /// #52 tagged MC/DC vector (obligation `index_864`): leaf A false — + /// #52 tagged MC/DC vector (obligation `index_868`): leaf A false — /// independence pair for A against - /// `mcdc__index_864__v1_in_range_and_matches` (short-circuits, so B + /// `mcdc__index_868__v1_in_range_and_matches` (short-circuits, so B /// is never evaluated). #[test] #[allow(non_snake_case)] - fn mcdc__index_864__v3_out_of_range() { + fn mcdc__index_868__v3_out_of_range() { let expect_order = ["key1"]; // `black_box` defeats constant-folding so rustc can't statically // prove `expect_order[idx]` out of bounds — it never runs, since diff --git a/src/btree/table/delete.rs b/src/btree/table/delete.rs index ed8cfeb0..035d2f73 100644 --- a/src/btree/table/delete.rs +++ b/src/btree/table/delete.rs @@ -320,16 +320,16 @@ mod tests { u32::from_be_bytes(page1[36..40].try_into().unwrap()) } - /// #52 tagged MC/DC vector (obligation `delete_62`, decision + /// #52 tagged MC/DC vector (obligation `delete_61`, decision /// `cells.len() > 1 || ancestors.is_empty()`): leaf A /// (`cells.len() > 1`) true, leaf B (`ancestors.is_empty()`) false — /// a multi-page tree where the leaf being deleted from still has /// other rows left, so it splices in place rather than collapsing. /// Independence pair for A against - /// `mcdc__delete_62__v2_last_cell_in_leaf_with_ancestors_collapses`. + /// `mcdc__delete_61__v2_last_cell_in_leaf_with_ancestors_collapses`. #[test] #[allow(non_snake_case)] - fn mcdc__delete_62__v1_leaf_survives_with_ancestors() { + fn mcdc__delete_61__v1_leaf_survives_with_ancestors() { let page_size = 512u32; let (vfs, header) = minimal_db(page_size); let mut pager = Pager::open(&vfs, Path::new("/test.db"), page_size).unwrap(); @@ -353,16 +353,16 @@ mod tests { assert!(delete_row(&mut pager, &header, 1, n - 1).is_ok()); } - /// #52 tagged MC/DC vector (obligation `delete_62`): both leaves + /// #52 tagged MC/DC vector (obligation `delete_61`): both leaves /// false — a multi-page tree where the leaf being deleted from holds /// exactly one cell, so it must be deallocated and its removal /// cascaded into ancestors rather than spliced in place. Independence - /// pair for A against `mcdc__delete_62__v1_leaf_survives_with_ancestors` + /// pair for A against `mcdc__delete_61__v1_leaf_survives_with_ancestors` /// and for B against - /// `mcdc__delete_62__v3_only_row_in_root_leaf_has_no_ancestors`. + /// `mcdc__delete_61__v3_only_row_in_root_leaf_has_no_ancestors`. #[test] #[allow(non_snake_case)] - fn mcdc__delete_62__v2_last_cell_in_leaf_with_ancestors_collapses() { + fn mcdc__delete_61__v2_last_cell_in_leaf_with_ancestors_collapses() { let page_size = 512u32; let (vfs, header) = minimal_db(page_size); let mut pager = Pager::open(&vfs, Path::new("/test.db"), page_size).unwrap(); @@ -394,14 +394,14 @@ mod tests { ); } - /// #52 tagged MC/DC vector (obligation `delete_62`): leaf A false, + /// #52 tagged MC/DC vector (obligation `delete_61`): leaf A false, /// leaf B (`ancestors.is_empty()`) true independently flips the /// outcome to true — the single-page root-leaf case, where the /// (empty) root can never be collapsed away. Independence pair for B - /// against `mcdc__delete_62__v2_last_cell_in_leaf_with_ancestors_collapses`. + /// against `mcdc__delete_61__v2_last_cell_in_leaf_with_ancestors_collapses`. #[test] #[allow(non_snake_case)] - fn mcdc__delete_62__v3_only_row_in_root_leaf_has_no_ancestors() { + fn mcdc__delete_61__v3_only_row_in_root_leaf_has_no_ancestors() { let page_size = 512u32; let (vfs, header) = minimal_db(page_size); let mut pager = Pager::open(&vfs, Path::new("/test.db"), page_size).unwrap(); diff --git a/src/parser/grammar.rs b/src/parser/grammar.rs index 29af1090..6b35dfc1 100644 --- a/src/parser/grammar.rs +++ b/src/parser/grammar.rs @@ -2420,36 +2420,36 @@ mod tests { Parser::new(Tokenizer::tokenize(sql)) } - /// #368 tagged MC/DC vector (obligation `grammar_246`, `parse_insert_stmt`'s + /// #368 tagged MC/DC vector (obligation `grammar_262`, `parse_insert_stmt`'s /// decision `self.at_kw(SELECT) || self.at_kw(WITH)`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_246__v1_select_source() { + fn mcdc__grammar_262__v1_select_source() { assert!(parser("INSERT INTO t SELECT * FROM u") .parse_insert_stmt() .is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_246`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_262`): both leaves /// false — neither VALUES/DEFAULT VALUES nor SELECT/WITH follows. /// Independence pair for A against - /// `mcdc__grammar_246__v1_select_source`. + /// `mcdc__grammar_262__v1_select_source`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_246__v2_neither_select_nor_with() { + fn mcdc__grammar_262__v2_neither_select_nor_with() { assert!(parser("INSERT INTO t FROM u").parse_insert_stmt().is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_246`): leaf B true, + /// #368 tagged MC/DC vector (obligation `grammar_262`): leaf B true, /// leaf A false. Independence pair for B against - /// `mcdc__grammar_246__v2_neither_select_nor_with`. #375 landed + /// `mcdc__grammar_262__v2_neither_select_nor_with`. #375 landed /// non-recursive `WITH`, so this now parses successfully instead of /// erroring out on the (then-)unimplemented WITH clause — the leaf - /// still exercises the WITH branch of `grammar_246`'s decision, just + /// still exercises the WITH branch of `grammar_262`'s decision, just /// via an `Ok` result now. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_246__v3_with_source() { + fn mcdc__grammar_262__v3_with_source() { assert!(parser("INSERT INTO t WITH x AS (SELECT 1) SELECT 1") .parse_insert_stmt() .is_ok()); @@ -2467,168 +2467,168 @@ mod tests { assert_eq!(insert.span.len, (sql.len() - 1) as u32); } - /// #368 tagged MC/DC vector (obligation `grammar_440`, + /// #368 tagged MC/DC vector (obligation `grammar_456`, /// `check_no_conflict_clause`'s decision `self.at_kw(ON) && /// matches!(peek_at(1).kind, Keyword(CONFLICT))`): both leaves true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_440__v1_on_conflict() { + fn mcdc__grammar_456__v1_on_conflict() { assert!(parser("ON CONFLICT").check_no_conflict_clause().is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_440`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_456`): both leaves /// false. Independence pair for A against - /// `mcdc__grammar_440__v1_on_conflict`. + /// `mcdc__grammar_456__v1_on_conflict`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_440__v2_no_on() { + fn mcdc__grammar_456__v2_no_on() { assert!(parser("NOT NULL").check_no_conflict_clause().is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_440`): leaf A true, + /// #368 tagged MC/DC vector (obligation `grammar_456`): leaf A true, /// leaf B false — `ON` not followed by `CONFLICT`. Independence pair - /// for B against `mcdc__grammar_440__v1_on_conflict`. + /// for B against `mcdc__grammar_456__v1_on_conflict`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_440__v3_on_but_not_conflict() { + fn mcdc__grammar_456__v3_on_but_not_conflict() { assert!(parser("ON DELETE").check_no_conflict_clause().is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_450`, + /// #368 tagged MC/DC vector (obligation `grammar_466`, /// `parse_create_table_stmt`'s decision `self.at_kw(TEMP) || /// self.at_kw(TEMPORARY)`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_450__v1_temp() { + fn mcdc__grammar_466__v1_temp() { assert!(parser("CREATE TEMP TABLE t (a)") .parse_create_table_stmt() .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_450`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_466`): both leaves /// false. Independence pair for A against - /// `mcdc__grammar_450__v1_temp`. + /// `mcdc__grammar_466__v1_temp`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_450__v2_neither() { + fn mcdc__grammar_466__v2_neither() { assert!(parser("CREATE TABLE t (a INTEGER)") .parse_create_table_stmt() .is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_450`): leaf B true, + /// #368 tagged MC/DC vector (obligation `grammar_466`): leaf B true, /// leaf A false. Independence pair for B against - /// `mcdc__grammar_450__v2_neither`. + /// `mcdc__grammar_466__v2_neither`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_450__v3_temporary() { + fn mcdc__grammar_466__v3_temporary() { assert!(parser("CREATE TEMPORARY TABLE t (a)") .parse_create_table_stmt() .is_err()); } - /// MC/DC vector (obligation `grammar_769`, `parse_create_view_stmt`'s + /// MC/DC vector (obligation `grammar_785`, `parse_create_view_stmt`'s /// decision `self.at_kw(TEMP) || self.at_kw(TEMPORARY)` — same shape - /// as `grammar_450`'s, at a distinct call site for CREATE VIEW): leaf + /// as `grammar_466`'s, at a distinct call site for CREATE VIEW): leaf /// A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_769__v1_temp() { + fn mcdc__grammar_785__v1_temp() { assert!(parser("CREATE TEMP VIEW v AS SELECT 1") .parse_create_view_stmt() .is_err()); } - /// MC/DC vector (obligation `grammar_769`): both leaves false. - /// Independence pair for A against `mcdc__grammar_769__v1_temp`. + /// MC/DC vector (obligation `grammar_785`): both leaves false. + /// Independence pair for A against `mcdc__grammar_785__v1_temp`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_769__v2_neither() { + fn mcdc__grammar_785__v2_neither() { assert!(parser("CREATE VIEW v AS SELECT 1") .parse_create_view_stmt() .is_ok()); } - /// MC/DC vector (obligation `grammar_769`): leaf B true, leaf A + /// MC/DC vector (obligation `grammar_785`): leaf B true, leaf A /// false. Independence pair for B against - /// `mcdc__grammar_769__v2_neither`. + /// `mcdc__grammar_785__v2_neither`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_769__v3_temporary() { + fn mcdc__grammar_785__v3_temporary() { assert!(parser("CREATE TEMPORARY VIEW v AS SELECT 1") .parse_create_view_stmt() .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_583`, + /// #368 tagged MC/DC vector (obligation `grammar_599`, /// `opt_column_constraint`'s `GENERATED ALWAYS AS` decision, 3 /// leaves / 4 required vectors): leaf A (`GENERATED`) true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_583__v1_generated() { + fn mcdc__grammar_599__v1_generated() { assert!(parser("GENERATED ALWAYS AS (1)") .opt_column_constraint() .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_583`): leaves A and + /// #368 tagged MC/DC vector (obligation `grammar_599`): leaves A and /// B (`AS`) both false — no recognized constraint at all. /// Independence pair for A against - /// `mcdc__grammar_583__v1_generated`. + /// `mcdc__grammar_599__v1_generated`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_583__v2_neither_generated_nor_as() { + fn mcdc__grammar_599__v2_neither_generated_nor_as() { assert_eq!(parser("").opt_column_constraint().unwrap(), None); } - /// #368 tagged MC/DC vector (obligation `grammar_583`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_599`): leaf A /// false, leaf B true, leaf C (`LParen` follows `AS`) false. - /// Independence pair for B against `mcdc__grammar_583__v2_neither_generated_nor_as`. + /// Independence pair for B against `mcdc__grammar_599__v2_neither_generated_nor_as`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_583__v3_as_without_paren() { + fn mcdc__grammar_599__v3_as_without_paren() { assert_eq!(parser("AS 1").opt_column_constraint().unwrap(), None); } - /// #368 tagged MC/DC vector (obligation `grammar_583`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_599`): leaf A /// false, leaves B and C both true. Independence pair for C against - /// `mcdc__grammar_583__v2_neither_generated_nor_as`. + /// `mcdc__grammar_599__v2_neither_generated_nor_as`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_583__v4_as_with_paren() { + fn mcdc__grammar_599__v4_as_with_paren() { assert!(parser("AS (1)").opt_column_constraint().is_err()); } - /// MC/DC vector (obligation `grammar_914`, `parse_pragma_stmt`'s + /// MC/DC vector (obligation `grammar_930`, `parse_pragma_stmt`'s /// decision `name.eq_ignore_ascii_case("integrity_check") || /// name.eq_ignore_ascii_case("quick_check")`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_914__v1_integrity_check() { + fn mcdc__grammar_930__v1_integrity_check() { assert!(parser("PRAGMA integrity_check").parse_pragma_stmt().is_ok()); } - /// MC/DC vector (obligation `grammar_914`): both leaves false. + /// MC/DC vector (obligation `grammar_930`): both leaves false. /// Independence pair for A against - /// `mcdc__grammar_914__v1_integrity_check`. + /// `mcdc__grammar_930__v1_integrity_check`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_914__v2_neither() { + fn mcdc__grammar_930__v2_neither() { assert!(parser("PRAGMA journal_mode = WAL") .parse_pragma_stmt() .is_ok()); } - /// MC/DC vector (obligation `grammar_914`): leaf B true, leaf A + /// MC/DC vector (obligation `grammar_930`): leaf B true, leaf A /// false. Independence pair for B against - /// `mcdc__grammar_914__v2_neither`. + /// `mcdc__grammar_930__v2_neither`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_914__v3_quick_check() { + fn mcdc__grammar_930__v3_quick_check() { assert!(parser("PRAGMA quick_check").parse_pragma_stmt().is_ok()); } - /// MC/DC vectors (obligation `grammar_1030`, `parse_select_stmt`'s + /// MC/DC vectors (obligation `grammar_1046`, `parse_select_stmt`'s /// `WITH ... INSERT/UPDATE/DELETE` decision `with_clause.is_some() /// && (self.at_kw(INSERT) || self.at_kw(UPDATE) || /// self.at_kw(DELETE))`, 4 leaves / 5 required vectors): baseline, @@ -2642,151 +2642,151 @@ mod tests { /// alone can't witness any leaf's effect; only the variant can. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1030__v1_with_then_select() { + fn mcdc__grammar_1046__v1_with_then_select() { assert!(parser("WITH cte AS (SELECT 1) SELECT 1") .parse_select_stmt() .is_ok()); } - /// MC/DC vector (obligation `grammar_1030`): leaf B true, leaf A + /// MC/DC vector (obligation `grammar_1046`): leaf B true, leaf A /// (`with_clause.is_some()`) false — no `WITH` at all, so this /// falls through to `expect_kw(SELECT)` and fails as `Invalid` - /// (not `Unsupported`), unlike `mcdc__grammar_1030__v3_with_insert` + /// (not `Unsupported`), unlike `mcdc__grammar_1046__v3_with_insert` /// below where only leaf A differs. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1030__v2_bare_insert_no_with() { + fn mcdc__grammar_1046__v2_bare_insert_no_with() { assert!(matches!( parser("INSERT INTO t VALUES (1)").parse_select_stmt(), Err(ParseFail::Invalid { .. }) )); } - /// MC/DC vector (obligation `grammar_1030`): leaves A and B both + /// MC/DC vector (obligation `grammar_1046`): leaves A and B both /// true. Independence pair for A against - /// `mcdc__grammar_1030__v2_bare_insert_no_with` (only A differs, + /// `mcdc__grammar_1046__v2_bare_insert_no_with` (only A differs, /// `Invalid` -> `Unsupported`) and for B against - /// `mcdc__grammar_1030__v1_with_then_select` (only B differs, `Ok` + /// `mcdc__grammar_1046__v1_with_then_select` (only B differs, `Ok` /// -> `Unsupported`). #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1030__v3_with_insert() { + fn mcdc__grammar_1046__v3_with_insert() { assert!(matches!( parser("WITH cte AS (SELECT 1) INSERT INTO t VALUES (1)").parse_select_stmt(), Err(ParseFail::Unsupported { .. }) )); } - /// MC/DC vector (obligation `grammar_1030`): leaves A and C both + /// MC/DC vector (obligation `grammar_1046`): leaves A and C both /// true. Independence pair for C against - /// `mcdc__grammar_1030__v1_with_then_select` (only C differs, `Ok` + /// `mcdc__grammar_1046__v1_with_then_select` (only C differs, `Ok` /// -> `Unsupported`). #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1030__v4_with_update() { + fn mcdc__grammar_1046__v4_with_update() { assert!(matches!( parser("WITH cte AS (SELECT 1) UPDATE t SET x = 1").parse_select_stmt(), Err(ParseFail::Unsupported { .. }) )); } - /// MC/DC vector (obligation `grammar_1030`): leaves A and D both + /// MC/DC vector (obligation `grammar_1046`): leaves A and D both /// true. Independence pair for D against - /// `mcdc__grammar_1030__v1_with_then_select` (only D differs, `Ok` + /// `mcdc__grammar_1046__v1_with_then_select` (only D differs, `Ok` /// -> `Unsupported`). #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1030__v5_with_delete() { + fn mcdc__grammar_1046__v5_with_delete() { assert!(matches!( parser("WITH cte AS (SELECT 1) DELETE FROM t").parse_select_stmt(), Err(ParseFail::Unsupported { .. }) )); } - /// #368 tagged MC/DC vector (obligation `grammar_1089`, + /// #368 tagged MC/DC vector (obligation `grammar_1105`, /// `parse_select_stmt`'s compound-operator decision /// `self.at_kw(INTERSECT) || self.at_kw(EXCEPT)`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1089__v1_intersect() { + fn mcdc__grammar_1105__v1_intersect() { assert!(parser("SELECT 1 INTERSECT SELECT 2") .parse_select_stmt() .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_1089`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_1105`): both leaves /// false — a non-compound SELECT. Independence pair for A against - /// `mcdc__grammar_1089__v1_intersect`. + /// `mcdc__grammar_1105__v1_intersect`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1089__v2_neither() { + fn mcdc__grammar_1105__v2_neither() { assert!(parser("SELECT 1").parse_select_stmt().is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_1089`): leaf B true, + /// #368 tagged MC/DC vector (obligation `grammar_1105`): leaf B true, /// leaf A false. Independence pair for B against - /// `mcdc__grammar_1089__v2_neither`. + /// `mcdc__grammar_1105__v2_neither`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1089__v3_except() { + fn mcdc__grammar_1105__v3_except() { assert!(parser("SELECT 1 EXCEPT SELECT 2") .parse_select_stmt() .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_1115`, + /// #368 tagged MC/DC vector (obligation `grammar_1131`, /// `parse_select_stmt`'s LIMIT-offset decision `self.eat_kw(OFFSET) /// || self.eat_punct(Comma)`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1115__v1_offset_keyword() { + fn mcdc__grammar_1131__v1_offset_keyword() { assert!(parser("SELECT 1 LIMIT 5 OFFSET 2") .parse_select_stmt() .is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_1115`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_1131`): both leaves /// false — a LIMIT with no offset at all. Independence pair for A - /// against `mcdc__grammar_1115__v1_offset_keyword`. + /// against `mcdc__grammar_1131__v1_offset_keyword`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1115__v2_no_offset() { + fn mcdc__grammar_1131__v2_no_offset() { assert!(parser("SELECT 1 LIMIT 5").parse_select_stmt().is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_1115`): leaf B true, + /// #368 tagged MC/DC vector (obligation `grammar_1131`): leaf B true, /// leaf A false — the comma-form offset. Independence pair for B - /// against `mcdc__grammar_1115__v2_no_offset`. + /// against `mcdc__grammar_1131__v2_no_offset`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1115__v3_comma_offset() { + fn mcdc__grammar_1131__v3_comma_offset() { assert!(parser("SELECT 1 LIMIT 5, 2").parse_select_stmt().is_ok()); } - /// MC/DC vector (obligation `grammar_1186`, + /// MC/DC vector (obligation `grammar_1202`, /// `parse_common_table_expr`'s `[NOT] MATERIALIZED` decision /// `self.at_kw(MATERIALIZED) || (self.at_kw(NOT) && /// matches!(peek_at(1).kind, Keyword(MATERIALIZED)))`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1186__v1_materialized() { + fn mcdc__grammar_1202__v1_materialized() { assert!(parser("cte AS MATERIALIZED (SELECT 1)") .parse_common_table_expr() .is_err()); } - /// MC/DC vector (obligation `grammar_1186`): all three leaves false + /// MC/DC vector (obligation `grammar_1202`): all three leaves false /// (no MATERIALIZED hint at all). Independence pair for A against - /// `mcdc__grammar_1186__v1_materialized`. + /// `mcdc__grammar_1202__v1_materialized`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1186__v2_neither_materialized_nor_not() { + fn mcdc__grammar_1202__v2_neither_materialized_nor_not() { assert!(parser("cte AS (SELECT 1)") .parse_common_table_expr() .is_ok()); } - /// MC/DC vector (obligation `grammar_1186`): leaves B and C both + /// MC/DC vector (obligation `grammar_1202`): leaves B and C both /// true (`NOT MATERIALIZED`), leaf A false. `at_kw` only peeks the /// current token, so B (current == NOT) and C (the *next* token == /// MATERIALIZED) are only jointly reachable together here — with A @@ -2795,16 +2795,16 @@ mod tests { /// just C from the other; this vector documents the one reachable /// true/true combination rather than claiming an unreachable /// independent split (same convention as `grammar_1647`/ - /// `mcdc__grammar_1882__v1_not_in`'s note elsewhere in this file). + /// `mcdc__grammar_1898__v1_not_in`'s note elsewhere in this file). #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1186__v3_not_materialized() { + fn mcdc__grammar_1202__v3_not_materialized() { assert!(parser("cte AS NOT MATERIALIZED (SELECT 1)") .parse_common_table_expr() .is_err()); } - /// MC/DC vector (obligation `grammar_1186`): leaf B true, leaf C + /// MC/DC vector (obligation `grammar_1202`): leaf B true, leaf C /// false (`NOT` not followed by `MATERIALIZED`), leaf A false. The /// overall decision is false here too (same as v2's all-false case) /// — `self.expect_punct(LParen)` then fails on the un-consumed `NOT` @@ -2815,19 +2815,19 @@ mod tests { /// defeated" spirit as v3 above. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1186__v4_not_without_materialized() { + fn mcdc__grammar_1202__v4_not_without_materialized() { assert!(parser("cte AS NOT (SELECT 1)") .parse_common_table_expr() .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_1288`, + /// #368 tagged MC/DC vector (obligation `grammar_1304`, /// `result_column`'s table-star lookahead /// `matches!(peek_at(1).kind, Dot) && matches!(peek_at(2).kind, Star)`): /// both leaves true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1288__v1_table_star() { + fn mcdc__grammar_1304__v1_table_star() { assert_eq!( parser("t.*").result_column().unwrap(), ResultColumn::TableStar { @@ -2836,97 +2836,97 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `grammar_1288`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_1304`): leaf A /// false — a bare identifier, no dot. Independence pair for A - /// against `mcdc__grammar_1288__v1_table_star`. + /// against `mcdc__grammar_1304__v1_table_star`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1288__v2_no_dot() { + fn mcdc__grammar_1304__v2_no_dot() { assert!(matches!( parser("t").result_column().unwrap(), ResultColumn::Expr { .. } )); } - /// #368 tagged MC/DC vector (obligation `grammar_1288`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_1304`): leaf A /// true, leaf B false — `table.column`, not `table.*`. Independence - /// pair for B against `mcdc__grammar_1288__v1_table_star`. + /// pair for B against `mcdc__grammar_1304__v1_table_star`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1288__v3_dot_but_not_star() { + fn mcdc__grammar_1304__v3_dot_but_not_star() { assert!(matches!( parser("t.a").result_column().unwrap(), ResultColumn::Expr { .. } )); } - /// #368 tagged MC/DC vector (obligation `grammar_1539`, `table_ref`'s + /// #368 tagged MC/DC vector (obligation `grammar_1555`, `table_ref`'s /// `NOT INDEXED` decision `self.at_kw(NOT) && /// matches!(peek_at(1).kind, Keyword(INDEXED))`): both leaves true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1539__v1_not_indexed() { + fn mcdc__grammar_1555__v1_not_indexed() { assert!(parser("t NOT INDEXED").table_ref().is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_1539`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_1555`): both leaves /// false — a plain table reference. Independence pair for A against - /// `mcdc__grammar_1539__v1_not_indexed`. + /// `mcdc__grammar_1555__v1_not_indexed`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1539__v2_neither() { + fn mcdc__grammar_1555__v2_neither() { assert!(parser("t").table_ref().is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_1539`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_1555`): leaf A /// true, leaf B false — `NOT` not followed by `INDEXED`. /// Independence pair for B against - /// `mcdc__grammar_1539__v1_not_indexed`. + /// `mcdc__grammar_1555__v1_not_indexed`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1539__v3_not_but_not_indexed() { + fn mcdc__grammar_1555__v3_not_but_not_indexed() { assert!(parser("t NOT foo").table_ref().is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_1862`, + /// #368 tagged MC/DC vector (obligation `grammar_1878`, /// `try_tuple_in_subquery`'s entry gate `!matches!(peek().kind, /// LParen) || !self.looks_like_tuple_in()`): leaf A true (not even a /// paren). #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1862__v1_not_a_paren() { + fn mcdc__grammar_1878__v1_not_a_paren() { assert_eq!(parser("1").try_tuple_in_subquery().unwrap(), None); } - /// #368 tagged MC/DC vector (obligation `grammar_1862`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_1878`): both leaves /// false — a real multi-column tuple-IN. Independence pair for A - /// against `mcdc__grammar_1862__v1_not_a_paren`. + /// against `mcdc__grammar_1878__v1_not_a_paren`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1862__v2_looks_like_tuple_in() { + fn mcdc__grammar_1878__v2_looks_like_tuple_in() { assert!(parser("(1, 2) IN (SELECT 1)") .try_tuple_in_subquery() .unwrap() .is_some()); } - /// #368 tagged MC/DC vector (obligation `grammar_1862`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_1878`): leaf A /// false (a paren), leaf B true — a single-element parenthesized /// expression, not a tuple-IN shape. Independence pair for B against - /// `mcdc__grammar_1862__v2_looks_like_tuple_in`. + /// `mcdc__grammar_1878__v2_looks_like_tuple_in`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1862__v3_paren_but_not_tuple_in_shape() { + fn mcdc__grammar_1878__v3_paren_but_not_tuple_in_shape() { assert_eq!( parser("(1) IN (SELECT 1)").try_tuple_in_subquery().unwrap(), None ); } - /// #368 tagged MC/DC vector (obligation `grammar_1882`, + /// #368 tagged MC/DC vector (obligation `grammar_1898`, /// `try_tuple_in_subquery`'s `NOT IN` decision `self.at_kw(NOT) && /// matches!(peek_at(1).kind, Keyword(IN))`). Note: `looks_like_tuple_in`'s - /// own gate (see `grammar_1862`) guarantees that whenever this elif + /// own gate (see `grammar_1878`) guarantees that whenever this elif /// is reached, both leaves are already true together — there is no /// reachable input where they disagree, so all three tagged vectors /// exercise the same (only reachable) true/true combination via @@ -2934,44 +2934,44 @@ mod tests { /// invariant. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1882__v1_not_in() { + fn mcdc__grammar_1898__v1_not_in() { assert!(parser("(1, 2) NOT IN (SELECT 1)") .try_tuple_in_subquery() .unwrap() .is_some()); } - /// #368 tagged MC/DC vector (obligation `grammar_1882`): see - /// `mcdc__grammar_1882__v1_not_in`'s note — a second, distinct + /// #368 tagged MC/DC vector (obligation `grammar_1898`): see + /// `mcdc__grammar_1898__v1_not_in`'s note — a second, distinct /// `NOT IN` call site. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1882__v2_not_in_three_columns() { + fn mcdc__grammar_1898__v2_not_in_three_columns() { assert!(parser("(1, 2, 3) NOT IN (SELECT 1)") .try_tuple_in_subquery() .unwrap() .is_some()); } - /// #368 tagged MC/DC vector (obligation `grammar_1882`): see - /// `mcdc__grammar_1882__v1_not_in`'s note — a third, distinct + /// #368 tagged MC/DC vector (obligation `grammar_1898`): see + /// `mcdc__grammar_1898__v1_not_in`'s note — a third, distinct /// `NOT IN` call site. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_1882__v3_not_in_text_values() { + fn mcdc__grammar_1898__v3_not_in_text_values() { assert!(parser("('a', 'b') NOT IN (SELECT 1)") .try_tuple_in_subquery() .unwrap() .is_some()); } - /// #368 tagged MC/DC vector (obligation `grammar_2185`, + /// #368 tagged MC/DC vector (obligation `grammar_2201`, /// `primary_expr`'s dotted-identifier-chain decision /// `matches!(peek().kind, Dot) && parts.len() < 3`): both leaves /// true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_2185__v1_chain_continues() { + fn mcdc__grammar_2201__v1_chain_continues() { let expr = parser("a.b").primary_expr().unwrap(); assert!(matches!( expr.kind, @@ -2979,23 +2979,23 @@ mod tests { )); } - /// #368 tagged MC/DC vector (obligation `grammar_2185`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_2201`): leaf A /// false — no dot at all. Independence pair for A against - /// `mcdc__grammar_2185__v1_chain_continues`. + /// `mcdc__grammar_2201__v1_chain_continues`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_2185__v2_no_dot() { + fn mcdc__grammar_2201__v2_no_dot() { let expr = parser("a").primary_expr().unwrap(); assert!(matches!(expr.kind, ExprKind::Column { table: None, name, .. } if name == "a")); } - /// #368 tagged MC/DC vector (obligation `grammar_2185`): leaf A + /// #368 tagged MC/DC vector (obligation `grammar_2201`): leaf A /// true, leaf B false — a 4th segment past the 3-part cap. /// Independence pair for B against - /// `mcdc__grammar_2185__v1_chain_continues`. + /// `mcdc__grammar_2201__v1_chain_continues`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_2185__v3_capped_at_three_parts() { + fn mcdc__grammar_2201__v3_capped_at_three_parts() { let expr = parser("a.b.c.d").primary_expr().unwrap(); assert!(matches!( expr.kind, @@ -3004,12 +3004,12 @@ mod tests { )); } - /// #368 tagged MC/DC vector (obligation `grammar_2270`, + /// #368 tagged MC/DC vector (obligation `grammar_2286`, /// `function_call`'s window-function decision `self.at_kw(OVER) || /// self.at_kw(FILTER)`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_2270__v1_over() { + fn mcdc__grammar_2286__v1_over() { assert!(parser("() OVER") .function_call( "f".to_string(), @@ -3023,12 +3023,12 @@ mod tests { .is_err()); } - /// #368 tagged MC/DC vector (obligation `grammar_2270`): both leaves + /// #368 tagged MC/DC vector (obligation `grammar_2286`): both leaves /// false — an ordinary function call. Independence pair for A - /// against `mcdc__grammar_2270__v1_over`. + /// against `mcdc__grammar_2286__v1_over`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_2270__v2_neither() { + fn mcdc__grammar_2286__v2_neither() { assert!(parser("()") .function_call( "f".to_string(), @@ -3042,12 +3042,12 @@ mod tests { .is_ok()); } - /// #368 tagged MC/DC vector (obligation `grammar_2270`): leaf B + /// #368 tagged MC/DC vector (obligation `grammar_2286`): leaf B /// true, leaf A false. Independence pair for B against - /// `mcdc__grammar_2270__v2_neither`. + /// `mcdc__grammar_2286__v2_neither`. #[test] #[allow(non_snake_case)] - fn mcdc__grammar_2270__v3_filter() { + fn mcdc__grammar_2286__v3_filter() { assert!(parser("() FILTER") .function_call( "f".to_string(), diff --git a/src/parser/tokenizer.rs b/src/parser/tokenizer.rs index 8cdcab60..d155737f 100644 --- a/src/parser/tokenizer.rs +++ b/src/parser/tokenizer.rs @@ -1536,139 +1536,139 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_783`, match guard + /// #368 tagged MC/DC vector (obligation `tokenizer_816`, match guard /// `c == 'x' || c == 'X'` dispatching to `scan_maybe_blob`): leaf A /// (`c == 'x'`) true. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_783__v1_lowercase_x() { + fn mcdc__tokenizer_816__v1_lowercase_x() { assert_eq!( kinds("x'41'"), vec![TokenKind::Blob(Box::new(vec![0x41])), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_783`): both + /// #368 tagged MC/DC vector (obligation `tokenizer_816`): both /// leaves false — falls through to the identifier-start arm. /// Independence pair for A against - /// `mcdc__tokenizer_783__v1_lowercase_x`. + /// `mcdc__tokenizer_816__v1_lowercase_x`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_783__v2_neither_x_nor_capital_x() { + fn mcdc__tokenizer_816__v2_neither_x_nor_capital_x() { assert_eq!( kinds("y"), vec![TokenKind::Identifier("y".to_string()), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_783`): leaf B + /// #368 tagged MC/DC vector (obligation `tokenizer_816`): leaf B /// (`c == 'X'`) true, leaf A false. Independence pair for B against - /// `mcdc__tokenizer_783__v2_neither_x_nor_capital_x`. + /// `mcdc__tokenizer_816__v2_neither_x_nor_capital_x`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_783__v3_uppercase_x() { + fn mcdc__tokenizer_816__v3_uppercase_x() { assert_eq!( kinds("X'41'"), vec![TokenKind::Blob(Box::new(vec![0x41])), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_831`, decision + /// #368 tagged MC/DC vector (obligation `tokenizer_864`, decision /// `!hex.len().is_multiple_of(2) || !hex.chars().all(is_ascii_hexdigit)`): /// leaf A (odd digit count) true. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_831__v1_odd_digit_count() { + fn mcdc__tokenizer_864__v1_odd_digit_count() { assert!(matches!(kinds("x'411'")[0], TokenKind::Error(_))); } - /// #368 tagged MC/DC vector (obligation `tokenizer_831`): both + /// #368 tagged MC/DC vector (obligation `tokenizer_864`): both /// leaves false — a valid, even-length, all-hex blob literal. /// Independence pair for A against - /// `mcdc__tokenizer_831__v1_odd_digit_count`. + /// `mcdc__tokenizer_864__v1_odd_digit_count`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_831__v2_valid_hex() { + fn mcdc__tokenizer_864__v2_valid_hex() { assert_eq!( kinds("x'41'"), vec![TokenKind::Blob(Box::new(vec![0x41])), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_831`): leaf B + /// #368 tagged MC/DC vector (obligation `tokenizer_864`): leaf B /// (a non-hex-digit character) true, leaf A false — even length, but /// not all hex digits. Independence pair for B against - /// `mcdc__tokenizer_831__v2_valid_hex`. + /// `mcdc__tokenizer_864__v2_valid_hex`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_831__v3_even_length_non_hex_digit() { + fn mcdc__tokenizer_864__v3_even_length_non_hex_digit() { assert!(matches!(kinds("x'4g'")[0], TokenKind::Error(_))); } - /// #368 tagged MC/DC vector (obligation `tokenizer_888`, decision + /// #368 tagged MC/DC vector (obligation `tokenizer_944`, decision /// `escapes && self.peek_char() == Some(close)` in /// `scan_quoted_identifier`): both leaves true — a doubled closing /// delimiter (`""`) inside a delimiter where open == close escapes. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_888__v1_escaped_doubled_delimiter() { + fn mcdc__tokenizer_944__v1_escaped_doubled_delimiter() { assert_eq!( kinds(r#""a""b""#), vec![TokenKind::Identifier("a\"b".to_string()), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_888`): leaf A + /// #368 tagged MC/DC vector (obligation `tokenizer_944`): leaf A /// (`escapes`) false — `[...]` has no escape mechanism (open != close), /// so leaf B is never even reached. Independence pair for A against - /// `mcdc__tokenizer_888__v1_escaped_doubled_delimiter`. + /// `mcdc__tokenizer_944__v1_escaped_doubled_delimiter`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_888__v2_bracket_identifier_does_not_escape() { + fn mcdc__tokenizer_944__v2_bracket_identifier_does_not_escape() { assert_eq!( kinds("[abc]"), vec![TokenKind::Identifier("abc".to_string()), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_888`): leaf A true, + /// #368 tagged MC/DC vector (obligation `tokenizer_944`): leaf A true, /// leaf B false — a simple double-quoted identifier with no doubled /// closing delimiter. Independence pair for B against - /// `mcdc__tokenizer_888__v1_escaped_doubled_delimiter`. + /// `mcdc__tokenizer_944__v1_escaped_doubled_delimiter`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_888__v3_unescaped_double_quoted() { + fn mcdc__tokenizer_944__v3_unescaped_double_quoted() { assert_eq!( kinds("\"abc\""), vec![TokenKind::Identifier("abc".to_string()), TokenKind::Eof] ); } - /// #368 tagged MC/DC vector (obligation `tokenizer_947`, decision + /// #368 tagged MC/DC vector (obligation `tokenizer_1013`, decision /// `self.peek_char() == Some('0') && matches!(self.peek_at(1), Some('x' | 'X'))` /// in `scan_number`): both leaves true — a hex literal. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_947__v1_hex_prefix() { + fn mcdc__tokenizer_1013__v1_hex_prefix() { assert_eq!(kinds("0x1A"), vec![TokenKind::Integer(26), TokenKind::Eof]); } - /// #368 tagged MC/DC vector (obligation `tokenizer_947`): leaf A + /// #368 tagged MC/DC vector (obligation `tokenizer_1013`): leaf A /// false — a number not starting with `0`. Independence pair for A - /// against `mcdc__tokenizer_947__v1_hex_prefix`. + /// against `mcdc__tokenizer_1013__v1_hex_prefix`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_947__v2_not_leading_zero() { + fn mcdc__tokenizer_1013__v2_not_leading_zero() { assert_eq!(kinds("123"), vec![TokenKind::Integer(123), TokenKind::Eof]); } - /// #368 tagged MC/DC vector (obligation `tokenizer_947`): leaf A + /// #368 tagged MC/DC vector (obligation `tokenizer_1013`): leaf A /// true, leaf B false — a leading zero not followed by `x`/`X`, /// parsed as a plain decimal integer. Independence pair for B against - /// `mcdc__tokenizer_947__v1_hex_prefix`. + /// `mcdc__tokenizer_1013__v1_hex_prefix`. #[test] #[allow(non_snake_case)] - fn mcdc__tokenizer_947__v3_leading_zero_not_hex() { + fn mcdc__tokenizer_1013__v3_leading_zero_not_hex() { assert_eq!(kinds("05"), vec![TokenKind::Integer(5), TokenKind::Eof]); } } diff --git a/src/record/encode.rs b/src/record/encode.rs index 31c18b86..39144b84 100644 --- a/src/record/encode.rs +++ b/src/record/encode.rs @@ -310,32 +310,32 @@ mod tests { assert_eq!(&payload[4..7], b"abc"); } - /// #368 tagged MC/DC vector (obligation `encode_17`, decision + /// #368 tagged MC/DC vector (obligation `encode_33`, decision /// `groups < 8 && value >= (1u64 << (7 * groups))`): both leaves true /// on the loop's first check — `groups` must grow past 1. #[test] #[allow(non_snake_case)] - fn mcdc__encode_17__v1_groups_grows() { + fn mcdc__encode_33__v1_groups_grows() { assert_eq!(encode_varint(128).len(), 2); } - /// #368 tagged MC/DC vector (obligation `encode_17`): leaf A + /// #368 tagged MC/DC vector (obligation `encode_33`): leaf A /// (`groups < 8`) true, leaf B false on the first check — the loop /// body never runs, `groups` stays 1. Independence pair for B against - /// `mcdc__encode_17__v1_groups_grows`. + /// `mcdc__encode_33__v1_groups_grows`. #[test] #[allow(non_snake_case)] - fn mcdc__encode_17__v2_groups_stays_one() { + fn mcdc__encode_33__v2_groups_stays_one() { assert_eq!(encode_varint(5).len(), 1); } - /// #368 tagged MC/DC vector (obligation `encode_17`): leaf A false + /// #368 tagged MC/DC vector (obligation `encode_33`): leaf A false /// (`groups` reaches 8, short-circuiting B) — the largest value still /// under the 9-byte-form threshold. Independence pair for A against - /// `mcdc__encode_17__v1_groups_grows`. + /// `mcdc__encode_33__v1_groups_grows`. #[test] #[allow(non_snake_case)] - fn mcdc__encode_17__v3_groups_caps_at_eight() { + fn mcdc__encode_33__v3_groups_caps_at_eight() { assert_eq!(encode_varint((1u64 << 56) - 1).len(), 8); } } diff --git a/src/vdbe/exec.rs b/src/vdbe/exec.rs index 27e50a72..431725a3 100644 --- a/src/vdbe/exec.rs +++ b/src/vdbe/exec.rs @@ -1494,32 +1494,32 @@ mod tests { assert_eq!(*vm.register(1).unwrap(), Value::Text("a".into())); } - /// #368 tagged MC/DC vector (obligation `exec_453`, decision + /// #368 tagged MC/DC vector (obligation `exec_444`, decision /// `reg < 0 || reg as usize > MAX_REGISTERS`): leaf A (`reg < 0`) true. #[test] #[allow(non_snake_case)] - fn mcdc__exec_453__v1_negative_register() { + fn mcdc__exec_444__v1_negative_register() { assert!(matches!( Vm::index("Test", -1), Err(ExecError::RegisterOutOfRange { index: -1, .. }) )); } - /// #368 tagged MC/DC vector (obligation `exec_453`): both leaves false. + /// #368 tagged MC/DC vector (obligation `exec_444`): both leaves false. /// Independence pair for A against - /// `mcdc__exec_453__v1_negative_register`. + /// `mcdc__exec_444__v1_negative_register`. #[test] #[allow(non_snake_case)] - fn mcdc__exec_453__v2_in_range() { + fn mcdc__exec_444__v2_in_range() { assert_eq!(Vm::index("Test", 5).unwrap(), 5); } - /// #368 tagged MC/DC vector (obligation `exec_453`): leaf B + /// #368 tagged MC/DC vector (obligation `exec_444`): leaf B /// (`reg as usize > MAX_REGISTERS`) true, leaf A false. Independence - /// pair for B against `mcdc__exec_453__v2_in_range`. + /// pair for B against `mcdc__exec_444__v2_in_range`. #[test] #[allow(non_snake_case)] - fn mcdc__exec_453__v3_over_max_registers() { + fn mcdc__exec_444__v3_over_max_registers() { let over = (MAX_REGISTERS as i32).saturating_add(1); assert!(matches!( Vm::index("Test", over), @@ -1527,12 +1527,12 @@ mod tests { )); } - /// #368 tagged MC/DC vector (obligation `exec_669`, decision + /// #368 tagged MC/DC vector (obligation `exec_664`, decision /// `matches!(a, Value::Null) || matches!(b, Value::Null)`): leaf A /// true. #[test] #[allow(non_snake_case)] - fn mcdc__exec_669__v1_left_operand_null() { + fn mcdc__exec_664__v1_left_operand_null() { let mut vm = Vm::new(); vm.set_register(0, Value::Null).unwrap(); vm.set_register(1, Value::Integer(1)).unwrap(); @@ -1543,12 +1543,12 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `exec_669`): both leaves + /// #368 tagged MC/DC vector (obligation `exec_664`): both leaves /// false. Independence pair for A against - /// `mcdc__exec_669__v1_left_operand_null`. + /// `mcdc__exec_664__v1_left_operand_null`. #[test] #[allow(non_snake_case)] - fn mcdc__exec_669__v2_neither_operand_null() { + fn mcdc__exec_664__v2_neither_operand_null() { let mut vm = Vm::new(); vm.set_register(0, Value::Integer(1)).unwrap(); vm.set_register(1, Value::Integer(1)).unwrap(); @@ -1559,12 +1559,12 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `exec_669`): leaf B true, + /// #368 tagged MC/DC vector (obligation `exec_664`): leaf B true, /// leaf A false. Independence pair for B against - /// `mcdc__exec_669__v2_neither_operand_null`. + /// `mcdc__exec_664__v2_neither_operand_null`. #[test] #[allow(non_snake_case)] - fn mcdc__exec_669__v3_right_operand_null() { + fn mcdc__exec_664__v3_right_operand_null() { let mut vm = Vm::new(); vm.set_register(0, Value::Integer(1)).unwrap(); vm.set_register(1, Value::Null).unwrap(); diff --git a/src/vdbe/functions.rs b/src/vdbe/functions.rs index ab8002fd..46fcc2e8 100644 --- a/src/vdbe/functions.rs +++ b/src/vdbe/functions.rs @@ -1069,12 +1069,12 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `functions_119`, `substr`'s + /// #368 tagged MC/DC vector (obligation `functions_121`, `substr`'s /// decision `matches!(args[1], Null) || args.get(2).is_some_and(is_null)`): /// leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_119__v1_start_arg_null() { + fn mcdc__functions_121__v1_start_arg_null() { assert_eq!( v( "substr", @@ -1084,12 +1084,12 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `functions_119`): both leaves + /// #368 tagged MC/DC vector (obligation `functions_121`): both leaves /// false. Independence pair for A against - /// `mcdc__functions_119__v1_start_arg_null`. + /// `mcdc__functions_121__v1_start_arg_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_119__v2_neither_null() { + fn mcdc__functions_121__v2_neither_null() { assert_eq!( v( "substr", @@ -1099,12 +1099,12 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `functions_119`): leaf B true, + /// #368 tagged MC/DC vector (obligation `functions_121`): leaf B true, /// leaf A false. Independence pair for B against - /// `mcdc__functions_119__v2_neither_null`. + /// `mcdc__functions_121__v2_neither_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_119__v3_length_arg_present_and_null() { + fn mcdc__functions_121__v3_length_arg_present_and_null() { assert_eq!( v( "substr", @@ -1118,83 +1118,83 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `functions_218`, `nullif`'s + /// #368 tagged MC/DC vector (obligation `functions_220`, `nullif`'s /// decision `matches!(a, Null) || matches!(b, Null)`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_218__v1_left_operand_null() { + fn mcdc__functions_220__v1_left_operand_null() { assert_eq!(v("nullif", &[Value::Null, Value::Integer(1)]), Value::Null); } - /// #368 tagged MC/DC vector (obligation `functions_218`): both + /// #368 tagged MC/DC vector (obligation `functions_220`): both /// leaves false. Independence pair for A against - /// `mcdc__functions_218__v1_left_operand_null`. + /// `mcdc__functions_220__v1_left_operand_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_218__v2_neither_null() { + fn mcdc__functions_220__v2_neither_null() { assert_eq!( v("nullif", &[Value::Integer(1), Value::Integer(2)]), Value::Integer(1) ); } - /// #368 tagged MC/DC vector (obligation `functions_218`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_220`): leaf B /// true, leaf A false. Independence pair for B against - /// `mcdc__functions_218__v2_neither_null`. + /// `mcdc__functions_220__v2_neither_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_218__v3_right_operand_null() { + fn mcdc__functions_220__v3_right_operand_null() { assert_eq!( v("nullif", &[Value::Integer(1), Value::Null]), Value::Integer(1) ); } - /// #368 tagged MC/DC vector (obligation `functions_341`, `round`'s + /// #368 tagged MC/DC vector (obligation `functions_343`, `round`'s /// decision `matches!(args[0], Null) || matches!(args.get(1), Some(Null))`): /// leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_341__v1_value_arg_null() { + fn mcdc__functions_343__v1_value_arg_null() { assert_eq!(v("round", &[Value::Null]), Value::Null); } - /// #368 tagged MC/DC vector (obligation `functions_341`): both + /// #368 tagged MC/DC vector (obligation `functions_343`): both /// leaves false. Independence pair for A against - /// `mcdc__functions_341__v1_value_arg_null`. + /// `mcdc__functions_343__v1_value_arg_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_341__v2_neither_null() { + fn mcdc__functions_343__v2_neither_null() { assert_eq!(v("round", &[Value::Real(1.5)]), Value::Real(2.0)); } - /// #368 tagged MC/DC vector (obligation `functions_341`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_343`): leaf B /// true, leaf A false. Independence pair for B against - /// `mcdc__functions_341__v2_neither_null`. + /// `mcdc__functions_343__v2_neither_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_341__v3_decimals_arg_present_and_null() { + fn mcdc__functions_343__v3_decimals_arg_present_and_null() { assert_eq!(v("round", &[Value::Real(1.5), Value::Null]), Value::Null); } - /// #368 tagged MC/DC vector (obligation `functions_374`, `instr`'s + /// #368 tagged MC/DC vector (obligation `functions_376`, `instr`'s /// decision `matches!(args[0], Null) || matches!(args[1], Null)`): /// leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_374__v1_haystack_null() { + fn mcdc__functions_376__v1_haystack_null() { assert_eq!( v("instr", &[Value::Null, Value::Text("a".to_string().into())]), Value::Null ); } - /// #368 tagged MC/DC vector (obligation `functions_374`): both + /// #368 tagged MC/DC vector (obligation `functions_376`): both /// leaves false. Independence pair for A against - /// `mcdc__functions_374__v1_haystack_null`. + /// `mcdc__functions_376__v1_haystack_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_374__v2_neither_null() { + fn mcdc__functions_376__v2_neither_null() { assert_eq!( v( "instr", @@ -1207,12 +1207,12 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `functions_374`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_376`): leaf B /// true, leaf A false. Independence pair for B against - /// `mcdc__functions_374__v2_neither_null`. + /// `mcdc__functions_376__v2_neither_null`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_374__v3_needle_null() { + fn mcdc__functions_376__v3_needle_null() { assert_eq!( v( "instr", @@ -1222,315 +1222,315 @@ mod tests { ); } - /// #368 tagged MC/DC vector (obligation `functions_502`, `like_rec`'s + /// #368 tagged MC/DC vector (obligation `functions_504`, `like_rec`'s /// escape-pair guard `Some(pc) == escape && pi.saturating_add(1) < p.len()`): /// both leaves true — an escape character followed by a literal. #[test] #[allow(non_snake_case)] - fn mcdc__functions_502__v1_escape_with_literal_following() { + fn mcdc__functions_504__v1_escape_with_literal_following() { assert!(like_rec(&['a'], &['\\', 'a'], Some('\\'), 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_502`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_504`): leaf A /// true, leaf B false — a trailing escape character with nothing /// after it, treated as a literal `\`. Independence pair for B - /// against `mcdc__functions_502__v1_escape_with_literal_following`. + /// against `mcdc__functions_504__v1_escape_with_literal_following`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_502__v2_trailing_escape_with_nothing_after() { + fn mcdc__functions_504__v2_trailing_escape_with_nothing_after() { assert!(like_rec(&['\\'], &['\\'], Some('\\'), 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_502`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_504`): leaf A /// false — the pattern character isn't the escape character. /// Independence pair for A against - /// `mcdc__functions_502__v1_escape_with_literal_following`. + /// `mcdc__functions_504__v1_escape_with_literal_following`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_502__v3_not_escape_character() { + fn mcdc__functions_504__v3_not_escape_character() { assert!(like_rec(&['a', 'b'], &['a', 'b'], Some('\\'), 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_504`, the + /// #368 tagged MC/DC vector (obligation `functions_506`, the /// escaped-literal match check `ti >= t.len() || !ascii_eq(t[ti], literal)`): /// leaf A true — text exhausted right at the escaped literal. #[test] #[allow(non_snake_case)] - fn mcdc__functions_504__v1_text_exhausted() { + fn mcdc__functions_506__v1_text_exhausted() { assert!(!like_rec(&[], &['\\', 'a'], Some('\\'), 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_504`): both + /// #368 tagged MC/DC vector (obligation `functions_506`): both /// leaves false — the escaped literal matches the next text char. /// Independence pair for A against - /// `mcdc__functions_504__v1_text_exhausted`. + /// `mcdc__functions_506__v1_text_exhausted`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_504__v2_literal_matches() { + fn mcdc__functions_506__v2_literal_matches() { assert!(like_rec(&['a'], &['\\', 'a'], Some('\\'), 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_504`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_506`): leaf B /// true, leaf A false — text present but doesn't match the escaped /// literal. Independence pair for B against - /// `mcdc__functions_504__v2_literal_matches`. + /// `mcdc__functions_506__v2_literal_matches`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_504__v3_literal_does_not_match() { + fn mcdc__functions_506__v3_literal_does_not_match() { assert!(!like_rec(&['y'], &['\\', 'x'], Some('\\'), 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_514`, the `%`-run + /// #368 tagged MC/DC vector (obligation `functions_516`, the `%`-run /// collapse `pi < p.len() && p[pi] == '%'`): both leaves true on /// entry. #[test] #[allow(non_snake_case)] - fn mcdc__functions_514__v1_percent_run_continues() { + fn mcdc__functions_516__v1_percent_run_continues() { assert!(like_rec(&['a'], &['%', 'a'], None, 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_514`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_516`): leaf A /// false — the loop reaches the end of the pattern (a pattern of /// only `%`). Independence pair for A against - /// `mcdc__functions_514__v1_percent_run_continues`. + /// `mcdc__functions_516__v1_percent_run_continues`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_514__v2_percent_runs_to_end_of_pattern() { + fn mcdc__functions_516__v2_percent_runs_to_end_of_pattern() { assert!(like_rec(&['x'], &['%'], None, 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_514`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_516`): leaf A /// true, leaf B false — the run stops because the next character /// isn't `%`. Independence pair for B against - /// `mcdc__functions_514__v1_percent_run_continues`. + /// `mcdc__functions_516__v1_percent_run_continues`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_514__v3_percent_run_stops_before_non_percent() { + fn mcdc__functions_516__v3_percent_run_stops_before_non_percent() { assert!(like_rec(&['b'], &['%', 'b'], None, 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_535`, `like_rec`'s + /// #368 tagged MC/DC vector (obligation `functions_537`, `like_rec`'s /// default-char match `ti >= t.len() || !ascii_eq(t[ti], pc)`): leaf /// A true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_535__v1_text_exhausted() { + fn mcdc__functions_537__v1_text_exhausted() { assert!(!like_rec(&[], &['a'], None, 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_535`): both + /// #368 tagged MC/DC vector (obligation `functions_537`): both /// leaves false. Independence pair for A against - /// `mcdc__functions_535__v1_text_exhausted`. + /// `mcdc__functions_537__v1_text_exhausted`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_535__v2_char_matches() { + fn mcdc__functions_537__v2_char_matches() { assert!(like_rec(&['a'], &['a'], None, 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_535`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_537`): leaf B /// true, leaf A false. Independence pair for B against - /// `mcdc__functions_535__v2_char_matches`. + /// `mcdc__functions_537__v2_char_matches`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_535__v3_char_does_not_match() { + fn mcdc__functions_537__v3_char_does_not_match() { assert!(!like_rec(&['b'], &['a'], None, 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_564`, `glob_rec`'s + /// #368 tagged MC/DC vector (obligation `functions_566`, `glob_rec`'s /// `*`-run collapse `pi < p.len() && p[pi] == '*'`): both leaves true /// on entry. #[test] #[allow(non_snake_case)] - fn mcdc__functions_564__v1_star_run_continues() { + fn mcdc__functions_566__v1_star_run_continues() { assert!(glob_rec(&['a'], &['*', 'a'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_564`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_566`): leaf A /// false — a pattern of only `*`. Independence pair for A against - /// `mcdc__functions_564__v1_star_run_continues`. + /// `mcdc__functions_566__v1_star_run_continues`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_564__v2_star_runs_to_end_of_pattern() { + fn mcdc__functions_566__v2_star_runs_to_end_of_pattern() { assert!(glob_rec(&['x'], &['*'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_564`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_566`): leaf A /// true, leaf B false — the run stops before a non-`*` char. /// Independence pair for B against - /// `mcdc__functions_564__v1_star_run_continues`. + /// `mcdc__functions_566__v1_star_run_continues`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_564__v3_star_run_stops_before_non_star() { + fn mcdc__functions_566__v3_star_run_stops_before_non_star() { assert!(glob_rec(&['a', 'b'], &['*', 'b'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_588`, `glob_rec`'s + /// #368 tagged MC/DC vector (obligation `functions_590`, `glob_rec`'s /// `[...]` class-match check `ti >= t.len() || !matches`): leaf A /// true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_588__v1_text_exhausted() { + fn mcdc__functions_590__v1_text_exhausted() { assert!(!glob_rec(&[], &['[', 'a', '-', 'c', ']'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_588`): both + /// #368 tagged MC/DC vector (obligation `functions_590`): both /// leaves false — the next char is inside the class range. /// Independence pair for A against - /// `mcdc__functions_588__v1_text_exhausted`. + /// `mcdc__functions_590__v1_text_exhausted`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_588__v2_class_matches() { + fn mcdc__functions_590__v2_class_matches() { assert!(glob_rec(&['b'], &['[', 'a', '-', 'c', ']'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_588`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_590`): leaf B /// true, leaf A false — text present but outside the class range. /// Independence pair for B against - /// `mcdc__functions_588__v2_class_matches`. + /// `mcdc__functions_590__v2_class_matches`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_588__v3_class_does_not_match() { + fn mcdc__functions_590__v3_class_does_not_match() { assert!(!glob_rec(&['z'], &['[', 'a', '-', 'c', ']'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_595`, `glob_rec`'s + /// #368 tagged MC/DC vector (obligation `functions_597`, `glob_rec`'s /// default-char match `ti >= t.len() || t[ti] != c`): leaf A true. #[test] #[allow(non_snake_case)] - fn mcdc__functions_595__v1_text_exhausted() { + fn mcdc__functions_597__v1_text_exhausted() { assert!(!glob_rec(&[], &['a'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_595`): both + /// #368 tagged MC/DC vector (obligation `functions_597`): both /// leaves false. Independence pair for A against - /// `mcdc__functions_595__v1_text_exhausted`. + /// `mcdc__functions_597__v1_text_exhausted`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_595__v2_char_matches() { + fn mcdc__functions_597__v2_char_matches() { assert!(glob_rec(&['a'], &['a'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_595`): leaf B + /// #368 tagged MC/DC vector (obligation `functions_597`): leaf B /// true, leaf A false. Independence pair for B against - /// `mcdc__functions_595__v2_char_matches`. + /// `mcdc__functions_597__v2_char_matches`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_595__v3_char_does_not_match() { + fn mcdc__functions_597__v3_char_does_not_match() { assert!(!glob_rec(&['b'], &['a'], 0, 0)); } - /// #368 tagged MC/DC vector (obligation `functions_619`, `glob_class`'s + /// #368 tagged MC/DC vector (obligation `functions_621`, `glob_class`'s /// terminator check `p[i] == ']' && i > class_start`): both leaves /// true — an ordinary class terminated by `]`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_619__v1_terminates_past_class_start() { + fn mcdc__functions_621__v1_terminates_past_class_start() { assert!(glob_class(&['[', 'a', 'b', ']'], 0, Some('a')).is_some()); } - /// #368 tagged MC/DC vector (obligation `functions_619`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_621`): leaf A /// false — an ordinary member character, not `]`. Independence pair - /// for A against `mcdc__functions_619__v1_terminates_past_class_start`. + /// for A against `mcdc__functions_621__v1_terminates_past_class_start`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_619__v2_non_terminator_char() { + fn mcdc__functions_621__v2_non_terminator_char() { assert!(glob_class(&['[', 'a', 'b', ']'], 0, Some('b')).is_some()); } - /// #368 tagged MC/DC vector (obligation `functions_619`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_621`): leaf A /// true, leaf B false — a literal `]` as the class's first member /// (`i == class_start`), per the `[]a]` SQLite convention. /// Independence pair for B against - /// `mcdc__functions_619__v1_terminates_past_class_start`. + /// `mcdc__functions_621__v1_terminates_past_class_start`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_619__v3_literal_close_bracket_as_first_member() { + fn mcdc__functions_621__v3_literal_close_bracket_as_first_member() { assert_eq!( glob_class(&['[', ']', 'a', ']'], 0, Some(']')), Some((true, 4)) ); } - /// #368 tagged MC/DC vector (obligation `functions_623`, `glob_class`'s + /// #368 tagged MC/DC vector (obligation `functions_625`, `glob_class`'s /// range-detection decision `i.saturating_add(2) < p.len() && /// p[i.saturating_add(1)] == '-' && p[i.saturating_add(2)] != ']'`, /// 3 leaves / 4 required vectors): all three leaves true — an actual /// `a-c` range. #[test] #[allow(non_snake_case)] - fn mcdc__functions_623__v1_all_true_actual_range() { + fn mcdc__functions_625__v1_all_true_actual_range() { assert_eq!( glob_class(&['[', 'a', '-', 'c', ']'], 0, Some('b')), Some((true, 5)) ); } - /// #368 tagged MC/DC vector (obligation `functions_623`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_625`): leaf A /// (`i+2 < p.len()`) false — too few characters left for a range. /// Independence pair for A against - /// `mcdc__functions_623__v1_all_true_actual_range`. + /// `mcdc__functions_625__v1_all_true_actual_range`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_623__v2_too_short_for_a_range() { + fn mcdc__functions_625__v2_too_short_for_a_range() { assert_eq!(glob_class(&['[', 'a', ']'], 0, Some('a')), Some((true, 3))); } - /// #368 tagged MC/DC vector (obligation `functions_623`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_625`): leaf A /// true, leaf B (`p[i+1] == '-'`) false — no dash follows. /// Independence pair for B against - /// `mcdc__functions_623__v1_all_true_actual_range`. + /// `mcdc__functions_625__v1_all_true_actual_range`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_623__v3_no_dash_follows() { + fn mcdc__functions_625__v3_no_dash_follows() { assert_eq!( glob_class(&['[', 'a', 'b', ']'], 0, Some('a')), Some((true, 4)) ); } - /// #368 tagged MC/DC vector (obligation `functions_623`): leaves A + /// #368 tagged MC/DC vector (obligation `functions_625`): leaves A /// and B true, leaf C (`p[i+2] != ']'`) false — a dash immediately /// followed by the closing bracket, not a real range. Independence - /// pair for C against `mcdc__functions_623__v1_all_true_actual_range`. + /// pair for C against `mcdc__functions_625__v1_all_true_actual_range`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_623__v4_dash_immediately_before_close() { + fn mcdc__functions_625__v4_dash_immediately_before_close() { assert_eq!( glob_class(&['[', 'a', '-', ']'], 0, Some('a')), Some((true, 4)) ); } - /// #368 tagged MC/DC vector (obligation `functions_629`, the range + /// #368 tagged MC/DC vector (obligation `functions_631`, the range /// membership check `c >= lo && c <= hi`): both leaves true — inside /// the range. #[test] #[allow(non_snake_case)] - fn mcdc__functions_629__v1_within_range() { + fn mcdc__functions_631__v1_within_range() { assert_eq!( glob_class(&['[', 'a', '-', 'c', ']'], 0, Some('b')), Some((true, 5)) ); } - /// #368 tagged MC/DC vector (obligation `functions_629`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_631`): leaf A /// (`c >= lo`) false. Independence pair for A against - /// `mcdc__functions_629__v1_within_range`. + /// `mcdc__functions_631__v1_within_range`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_629__v2_below_range() { + fn mcdc__functions_631__v2_below_range() { assert_eq!( glob_class(&['[', 'a', '-', 'c', ']'], 0, Some('0')), Some((false, 5)) ); } - /// #368 tagged MC/DC vector (obligation `functions_629`): leaf A + /// #368 tagged MC/DC vector (obligation `functions_631`): leaf A /// true, leaf B (`c <= hi`) false — above the range. Independence - /// pair for B against `mcdc__functions_629__v1_within_range`. + /// pair for B against `mcdc__functions_631__v1_within_range`. #[test] #[allow(non_snake_case)] - fn mcdc__functions_629__v3_above_range() { + fn mcdc__functions_631__v3_above_range() { assert_eq!( glob_class(&['[', 'a', '-', 'c', ']'], 0, Some('d')), Some((false, 5)) diff --git a/tests/mcdc/obligations.json b/tests/mcdc/obligations.json index 7833bbb2..41d113a6 100644 --- a/tests/mcdc/obligations.json +++ b/tests/mcdc/obligations.json @@ -1,4752 +1,4887 @@ [ { - "id": "btree_81", + "id": "btree_83", "file": "src/btree.rs", - "line": 81, + "line": 83, "decision": "match self {\n #[allow(\n clippy::indexing_slicing,\n reason = \"start/len are computed from a validated in-bounds slice at construction (reassemble_payload)\"\n )]\n Payload::Local { page, start, len } => &page[*start..start.saturating_add(*len)],\n Payload::Owned(bytes) => bytes,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_238", + "id": "btree_240", "file": "src/btree.rs", - "line": 238, + "line": 240, "decision": "!self.positioned_reverse", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_297", + "id": "btree_299", "file": "src/btree.rs", - "line": 297, + "line": 299, "decision": "visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_310", + "id": "btree_312", "file": "src/btree.rs", - "line": 310, - "decision": "match page_type {\n LEAF_TABLE => {\n let cell_ptr_base = header_start.saturating_add(8);\n // Leaf cells are stored in rowid-ascending order by\n // pointer-array index (see the module's ordering\n // invariant), so a binary search over `i` decodes only\n // O(log n) cells instead of scanning every cell on the\n // page — this matters a lot for repeated seeks (e.g. a\n // join probing the same small table per outer row).\n let mut lo = 0usize;\n let mut hi = num_cells;\n while lo < hi {\n let mid = lo.saturating_add(hi.saturating_sub(lo) / 2);\n let cell_start = read_cell_pointer(\n &page,\n cell_ptr_offset(cell_ptr_base, mid),\n page_num,\n mid,\n )?;\n let (rowid, payload_len, tail_start) =\n decode_cell_head(&page, cell_start, page_num)?;\n match rowid.cmp(&target_rowid) {\n std::cmp::Ordering::Equal => {\n self.current = Some(CurrentCell {\n page: Rc::clone(&page),\n page_num,\n tail_start,\n payload_len,\n });\n return Ok(Some(rowid));\n }\n std::cmp::Ordering::Less => lo = mid.saturating_add(1),\n std::cmp::Ordering::Greater => hi = mid,\n }\n }\n return Ok(None);\n }\n INTERIOR_TABLE => {\n require_interior_header(&page, header_start, page_num)?;\n let cell_ptr_base = header_start.saturating_add(12);\n let rightmost = read_u32(&page, header_start.saturating_add(8), page_num)?;\n // Interior separator keys are ascending by pointer-array\n // index too; binary search for the leftmost `i` with\n // `target_rowid <= key(i)` (the child to descend into),\n // falling back to `rightmost` when none qualifies —\n // same semantics as the old early-break linear scan.\n let mut lo = 0usize;\n let mut hi = num_cells;\n let mut next_page = rightmost;\n while lo < hi {\n let mid = lo.saturating_add(hi.saturating_sub(lo) / 2);\n let cell_start = read_cell_pointer(\n &page,\n cell_ptr_offset(cell_ptr_base, mid),\n page_num,\n mid,\n )?;\n let key_bytes = page.get(cell_start.saturating_add(4)..).ok_or(\n BtreeError::InvalidCellPointer {\n page_num,\n index: mid,\n },\n )?;\n let (key, _) = decode_varint(key_bytes)\n .map_err(|source| BtreeError::InvalidCellVarint { page_num, source })?;\n if target_rowid <= key as i64 {\n let child = read_u32(&page, cell_start, page_num)?;\n next_page = child;\n hi = mid;\n } else {\n lo = mid.saturating_add(1);\n }\n }\n page_num = next_page;\n }\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num,\n page_type: other,\n })\n }\n }", + "line": 312, + "decision": "match page_type {\n LEAF_TABLE => {\n let cell_ptr_base = header_start.saturating_add(8);\n // Leaf cells are stored in rowid-ascending order by\n // pointer-array index (see the module's ordering\n // invariant), so a binary search over `i` decodes only\n // O(log n) cells instead of scanning every cell on the\n // page — this matters a lot for repeated seeks (e.g. a\n // join probing the same small table per outer row).\n let mut lo = 0usize;\n let mut hi = num_cells;\n while lo < hi {\n let mid = lo.saturating_add(hi.saturating_sub(lo) / 2);\n let cell_start = read_cell_pointer(\n &page,\n cell_ptr_offset(cell_ptr_base, mid),\n page_num,\n mid,\n )?;\n let (rowid, payload_len, tail_start) =\n decode_cell_head(&page, cell_start, page_num)?;\n match rowid.cmp(&target_rowid) {\n std::cmp::Ordering::Equal => {\n self.current = Some(CurrentCell {\n page: Rc::clone(&page),\n page_num,\n tail_start,\n payload_len,\n });\n return Ok(Some(rowid));\n }\n std::cmp::Ordering::Less => lo = mid.saturating_add(1),\n std::cmp::Ordering::Greater => hi = mid,\n }\n }\n return Ok(None);\n }\n INTERIOR_TABLE => {\n require_interior_header(&page, header_start, page_num)?;\n let cell_ptr_base = header_start.saturating_add(12);\n let rightmost = read_u32(&page, header_start.saturating_add(8), page_num)?;\n // Interior separator keys are ascending by pointer-array\n // index too; binary search for the leftmost `i` with\n // `target_rowid <= key(i)` (the child to descend into),\n // falling back to `rightmost` when none qualifies —\n // same semantics as the old early-break linear scan.\n let mut lo = 0usize;\n let mut hi = num_cells;\n let mut next_page = rightmost;\n while lo < hi {\n let mid = lo.saturating_add(hi.saturating_sub(lo) / 2);\n let cell_start = read_cell_pointer(\n &page,\n cell_ptr_offset(cell_ptr_base, mid),\n page_num,\n mid,\n )?;\n let key_bytes = page.get(cell_start.saturating_add(4)..).ok_or({\n BtreeError::InvalidCellPointer {\n page_num,\n index: mid,\n }\n })?;\n let (key, _) = decode_varint(key_bytes)\n .map_err(|source| BtreeError::InvalidCellVarint { page_num, source })?;\n if target_rowid <= key as i64 {\n let child = read_u32(&page, cell_start, page_num)?;\n next_page = child;\n hi = mid;\n } else {\n lo = mid.saturating_add(1);\n }\n }\n page_num = next_page;\n }\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num,\n page_type: other,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_321", + "id": "btree_323", "file": "src/btree.rs", - "line": 321, + "line": 323, "decision": "lo < hi", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_331", + "id": "btree_333", "file": "src/btree.rs", - "line": 331, + "line": 333, "decision": "match rowid.cmp(&target_rowid) {\n std::cmp::Ordering::Equal => {\n self.current = Some(CurrentCell {\n page: Rc::clone(&page),\n page_num,\n tail_start,\n payload_len,\n });\n return Ok(Some(rowid));\n }\n std::cmp::Ordering::Less => lo = mid.saturating_add(1),\n std::cmp::Ordering::Greater => hi = mid,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_359", + "id": "btree_361", "file": "src/btree.rs", - "line": 359, + "line": 361, "decision": "lo < hi", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_375", + "id": "btree_377", "file": "src/btree.rs", - "line": 375, + "line": 377, "decision": "target_rowid <= key as i64", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_407", + "id": "btree_409", "file": "src/btree.rs", - "line": 407, + "line": 409, "decision": "self.pages_visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_427", + "id": "btree_429", "file": "src/btree.rs", - "line": 427, + "line": 429, "decision": "match page_type {\n LEAF_TABLE => false,\n INTERIOR_TABLE => true,\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num,\n page_type: other,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_437", + "id": "btree_439", "file": "src/btree.rs", - "line": 437, + "line": 439, "decision": "is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_441", + "id": "btree_443", "file": "src/btree.rs", - "line": 441, + "line": 443, "decision": "is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_454", + "id": "btree_456", "file": "src/btree.rs", - "line": 454, + "line": 456, "decision": "reverse", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_468", + "id": "btree_470", "file": "src/btree.rs", - "line": 468, + "line": 470, "decision": "match self.stack.len() {\n 0 => {\n self.current = None;\n return Ok(None);\n }\n n => n.saturating_sub(1),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_486", + "id": "btree_488", "file": "src/btree.rs", - "line": 486, + "line": 488, "decision": "!is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_487", + "id": "btree_489", "file": "src/btree.rs", - "line": 487, + "line": 489, "decision": "next_cell >= num_cells", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_495", + "id": "btree_497", "file": "src/btree.rs", - "line": 495, + "line": 497, "decision": "next_cell < num_cells", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_499", + "id": "btree_501", "file": "src/btree.rs", - "line": 499, + "line": 501, "decision": "!rightmost_done", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_526", + "id": "btree_528", "file": "src/btree.rs", - "line": 526, + "line": 528, "decision": "match self.stack.len() {\n 0 => {\n self.current = None;\n return Ok(None);\n }\n n => n.saturating_sub(1),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_538", + "id": "btree_540", "file": "src/btree.rs", - "line": 538, + "line": 540, "decision": "!is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_539", + "id": "btree_541", "file": "src/btree.rs", - "line": 539, + "line": 541, "decision": "next_cell == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_548", + "id": "btree_550", "file": "src/btree.rs", - "line": 548, + "line": 550, "decision": "!rightmost_done", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_551", + "id": "btree_553", "file": "src/btree.rs", - "line": 551, + "line": 553, "decision": "next_cell > 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_615", + "id": "btree_617", "file": "src/btree.rs", - "line": 615, + "line": 617, "decision": "payload_len <= max_local", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_626", + "id": "btree_628", "file": "src/btree.rs", - "line": 626, + "line": 628, "decision": "k <= max_local", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_641", + "id": "btree_643", "file": "src/btree.rs", - "line": 641, + "line": 643, "decision": "payload_len > MAX_PAYLOAD_LEN", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_654", + "id": "btree_656", "file": "src/btree.rs", - "line": 654, + "line": 656, "decision": "local_size as u64 == payload_len", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_684", + "id": "btree_690", "file": "src/btree.rs", - "line": 684, + "line": 690, "decision": "remaining > 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_685", + "id": "btree_691", "file": "src/btree.rs", - "line": 685, + "line": 691, "decision": "overflow_page == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_688", + "id": "btree_694", "file": "src/btree.rs", - "line": 688, + "line": 694, "decision": "!visited_overflow_pages.insert(overflow_page)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_695", + "id": "btree_701", "file": "src/btree.rs", - "line": 695, + "line": 701, "decision": "hops > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_735", + "id": "btree_741", "file": "src/btree.rs", - "line": 735, + "line": 741, "decision": "visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_745", + "id": "btree_751", "file": "src/btree.rs", - "line": 745, + "line": 751, "decision": "page_type == LEAF_TABLE", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_747", + "id": "btree_753", "file": "src/btree.rs", - "line": 747, + "line": 753, "decision": "page_type == INTERIOR_TABLE", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_752", + "id": "btree_758", "file": "src/btree.rs", - "line": 752, + "line": 758, "decision": "rowid <= *key", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_800", + "id": "btree_806", "file": "src/btree.rs", - "line": 800, + "line": 806, "decision": "*visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_810", + "id": "btree_816", "file": "src/btree.rs", - "line": 810, + "line": 816, "decision": "match page_type {\n LEAF_TABLE => {}\n INTERIOR_TABLE => {\n let (entries, rightmost) = collect_interior_entries(&buf, header_start, page_num)?;\n for (child, _) in &entries {\n free_btree_pages_inner(pager, *child, usable_size, encoding, visited)?;\n }\n free_btree_pages_inner(pager, rightmost, usable_size, encoding, visited)?;\n }\n t if t == index::LEAF_INDEX => {}\n t if t == index::INTERIOR_INDEX => {\n let (entries, rightmost) = index::collect_index_interior_entries(\n &*pager,\n &buf,\n header_start,\n page_num,\n usable_size,\n encoding,\n )?;\n for (child, _, _) in &entries {\n free_btree_pages_inner(pager, *child, usable_size, encoding, visited)?;\n }\n free_btree_pages_inner(pager, rightmost, usable_size, encoding, visited)?;\n }\n _ => {\n return Err(BtreeError::UnexpectedPageType {\n page_num,\n page_type,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_819", + "id": "btree_825", "file": "src/btree.rs", - "line": 819, + "line": 825, "decision": "t == index::LEAF_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_820", + "id": "btree_826", "file": "src/btree.rs", - "line": 820, + "line": 826, "decision": "t == index::INTERIOR_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_867", + "id": "btree_873", "file": "src/btree.rs", - "line": 867, + "line": 873, "decision": "*visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_877", + "id": "btree_883", "file": "src/btree.rs", - "line": 877, + "line": 883, "decision": "match page_type {\n LEAF_TABLE => {\n let num_cells = read_num_cells(&buf, header_start, page_num)?;\n #[allow(\n clippy::cast_possible_wrap,\n reason = \"num_cells is a page's cell count, always <= u16::MAX by file-format construction\"\n )]\n let num_cells = num_cells as i64;\n *total = total.saturating_add(num_cells);\n }\n INTERIOR_TABLE => {\n let (entries, rightmost) = collect_interior_entries(&buf, header_start, page_num)?;\n for (child, _) in &entries {\n count_table_rows_inner(source, *child, visited, total)?;\n }\n count_table_rows_inner(source, rightmost, visited, total)?;\n }\n _ => {\n return Err(BtreeError::UnexpectedPageType {\n page_num,\n page_type,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_926", + "id": "btree_932", "file": "src/btree.rs", - "line": 926, + "line": 932, "decision": "has_overflow", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1076", + "id": "btree_963", "file": "src/btree.rs", - "line": 1076, + "line": 963, + "decision": "cell_rowid == rowid", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "btree_966", + "file": "src/btree.rs", + "line": 966, + "decision": "cell_rowid > rowid && insert_pos == num_cells", + "conditions": 2, + "vectors_required": 3, + "compiler_void": false + }, + { + "id": "btree_973", + "file": "src/btree.rs", + "line": 973, + "decision": "has_overflow", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "btree_974", + "file": "src/btree.rs", + "line": 974, + "decision": "cell_end > buf.len()", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "btree_1000", + "file": "src/btree.rs", + "line": 1000, + "decision": "cell_rowid != rowid", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "btree_1004", + "file": "src/btree.rs", + "line": 1004, + "decision": "(local_size as u64) < payload_len", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "btree_1154", + "file": "src/btree.rs", + "line": 1154, "decision": "*off >= 65536", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1095", + "id": "btree_1173", "file": "src/btree.rs", - "line": 1095, + "line": 1173, "decision": "content_end >= 65536", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1152", + "id": "btree_1230", "file": "src/btree.rs", - "line": 1152, + "line": 1230, "decision": "v == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1161", + "id": "btree_1239", "file": "src/btree.rs", - "line": 1161, + "line": 1239, "decision": "value >= 65536", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1208", + "id": "btree_1286", "file": "src/btree.rs", - "line": 1208, + "line": 1286, "decision": "off != 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1210", + "id": "btree_1288", "file": "src/btree.rs", - "line": 1210, + "line": 1288, "decision": "n > MAX_FREEBLOCKS", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1254", + "id": "btree_1332", "file": "src/btree.rs", - "line": 1254, + "line": 1332, "decision": "insert_pos > 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1256", + "id": "btree_1334", "file": "src/btree.rs", - "line": 1256, + "line": 1334, "decision": "prev_off.saturating_add(prev_size) == new_start", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1265", + "id": "btree_1343", "file": "src/btree.rs", - "line": 1265, + "line": 1343, "decision": "new_start.saturating_add(new_size) == next_off", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1296", + "id": "btree_1374", "file": "src/btree.rs", - "line": 1296, + "line": 1374, "decision": "content_start < ptr_end || content_start.saturating_sub(ptr_end) < needed", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "btree_1340", + "id": "btree_1418", "file": "src/btree.rs", - "line": 1340, + "line": 1418, "decision": "index >= num_cells", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1348", + "id": "btree_1426", "file": "src/btree.rs", - "line": 1348, + "line": 1426, "decision": "has_rowid", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1358", + "id": "btree_1436", "file": "src/btree.rs", - "line": 1358, + "line": 1436, "decision": "has_overflow", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1375", + "id": "btree_1453", "file": "src/btree.rs", - "line": 1375, + "line": 1453, "decision": "cell_start == content_start", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1384", + "id": "btree_1462", "file": "src/btree.rs", - "line": 1384, + "line": 1462, "decision": "cell_len < MIN_FREEBLOCK_SIZE", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1401", + "id": "btree_1479", "file": "src/btree.rs", - "line": 1401, + "line": 1479, "decision": "page_num == 1", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1439", + "id": "btree_1517", "file": "src/btree.rs", - "line": 1439, + "line": 1517, "decision": "page.len() < header_start.saturating_add(12)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_1576", + "id": "btree_1654", "file": "src/btree.rs", - "line": 1576, + "line": 1654, "decision": "match v {\n Value::Text(s) => s,\n other => panic!(\"expected text, got {other:?}\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_1583", + "id": "btree_1661", "file": "src/btree.rs", - "line": 1583, + "line": 1661, "decision": "match v {\n Value::Integer(i) => *i,\n other => panic!(\"expected integer, got {other:?}\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_1590", + "id": "btree_1668", "file": "src/btree.rs", - "line": 1590, + "line": 1668, "decision": "match v {\n Value::Blob(b) => b,\n other => panic!(\"expected blob, got {other:?}\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "btree_1868", + "id": "btree_1946", "file": "src/btree.rs", - "line": 1868, + "line": 1946, "decision": "msg.len() % 64 != 56", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_2075", + "id": "btree_2153", "file": "src/btree.rs", - "line": 2075, + "line": 2153, "decision": "value < 0x80", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_2083", + "id": "btree_2161", "file": "src/btree.rs", - "line": 2083, + "line": 2161, "decision": "value == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_2089", + "id": "btree_2167", "file": "src/btree.rs", - "line": 2089, + "line": 2167, "decision": "i + 1 == chunks.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "btree_2180", + "id": "btree_2258", "file": "src/btree.rs", - "line": 2180, + "line": 2258, "decision": "match &row.payload {\n Payload::Local { page, .. } => {\n assert!(\n Rc::strong_count(page) >= 2,\n \"expected the row to share the page's Rc, not hold the only reference\"\n );\n }\n Payload::Owned(_) => panic!(\"expected a borrowed Local payload, got an Owned copy\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "error_151", + "id": "error_153", "file": "src/btree/error.rs", - "line": 151, + "line": 153, "decision": "match self {\n BtreeError::InvalidKeyRecord(source) => write!(f, \"decoding a key record: {source}\"),\n BtreeError::PageSource { page_num, source } => {\n write!(f, \"reading page {page_num}: {source}\")\n }\n BtreeError::PageTooShort { page_num, len } => write!(\n f,\n \"page {page_num} is too short ({len} bytes) to contain a b-tree page header\"\n ),\n BtreeError::CursorNotPositioned {\n operation,\n required,\n } => write!(\n f,\n \"{operation} called on a cursor that was never positioned by {required}\"\n ),\n BtreeError::UnexpectedPageType {\n page_num,\n page_type,\n } => write!(\n f,\n \"page {page_num} has unexpected b-tree page type {page_type:#x}\"\n ),\n BtreeError::InvalidCellPointer { page_num, index } => write!(\n f,\n \"page {page_num} cell pointer at index {index} is out of bounds\"\n ),\n BtreeError::InvalidCellVarint { page_num, source } => {\n write!(f, \"page {page_num} cell varint decode failed: {source}\")\n }\n BtreeError::PayloadTooShort { page_num } => write!(\n f,\n \"page {page_num} cell payload is shorter than its declared local size\"\n ),\n BtreeError::PayloadTooLarge {\n page_num,\n payload_len,\n } => write!(\n f,\n \"page {page_num} declares an implausible payload length {payload_len}\"\n ),\n BtreeError::OverflowChainTooLong { page_num, max } => write!(\n f,\n \"overflow chain from page {page_num} exceeded {max} pages (possible cycle)\"\n ),\n BtreeError::OverflowChainCycle {\n page_num,\n revisited_page,\n } => write!(\n f,\n \"overflow chain from page {page_num} revisited page {revisited_page} (cycle)\"\n ),\n BtreeError::OverflowChainTruncated { page_num } => write!(\n f,\n \"overflow chain from page {page_num} ended before all payload bytes were read\"\n ),\n BtreeError::TraversalTooLong { max } => write!(\n f,\n \"b-tree traversal visited more than {max} pages (possible cycle)\"\n ),\n BtreeError::Pager(source) => write!(f, \"pager error: {source}\"),\n BtreeError::DuplicateRowid { rowid } => {\n write!(f, \"cannot insert duplicate rowid {rowid}\")\n }\n BtreeError::MissingChildRoute { page_num, child } => write!(\n f,\n \"interior page {page_num} has no routing entry for child page {child}\"\n ),\n BtreeError::RowidNotFound { rowid } => {\n write!(f, \"cannot delete rowid {rowid}: no such row\")\n }\n BtreeError::DuplicateKey => write!(f, \"cannot insert duplicate index key\"),\n BtreeError::KeyNotFound => write!(f, \"cannot delete index key: no such entry\"),\n BtreeError::InvalidRootPage { name, rootpage } => write!(\n f,\n \"sqlite_master entry {name:?} has out-of-range rootpage {rootpage}\"\n ),\n BtreeError::MasterEntryNotFound { name } => write!(\n f,\n \"cannot delete sqlite_master entry {name:?}: no such entry\"\n ),\n BtreeError::Internal(msg) => write!(f, \"internal invariant violated: {msg}\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_146", + "id": "index_148", "file": "src/btree/index.rs", - "line": 146, + "line": 148, "decision": "compare_keys(&key, target) != Ordering::Less", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_156", + "id": "index_158", "file": "src/btree/index.rs", - "line": 156, + "line": 158, "decision": "self.pages_visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_170", + "id": "index_172", "file": "src/btree/index.rs", - "line": 170, + "line": 172, "decision": "match page_type {\n LEAF_INDEX => false,\n INTERIOR_INDEX => true,\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num,\n page_type: other,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_180", + "id": "index_182", "file": "src/btree/index.rs", - "line": 180, + "line": 182, "decision": "is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_184", + "id": "index_186", "file": "src/btree/index.rs", - "line": 184, + "line": 186, "decision": "is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_210", + "id": "index_212", "file": "src/btree/index.rs", - "line": 210, + "line": 212, "decision": "match self.stack.len() {\n 0 => return Ok(None),\n n => n.saturating_sub(1),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_219", + "id": "index_221", "file": "src/btree/index.rs", - "line": 219, + "line": 221, "decision": "!is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_220", + "id": "index_222", "file": "src/btree/index.rs", - "line": 220, + "line": 222, "decision": "step >= num_cells", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_229", + "id": "index_231", "file": "src/btree/index.rs", - "line": 229, + "line": 231, "decision": "step > total_steps", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_234", + "id": "index_236", "file": "src/btree/index.rs", - "line": 234, + "line": 236, "decision": "step == total_steps", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_236", + "id": "index_238", "file": "src/btree/index.rs", - "line": 236, + "line": 238, "decision": "step % 2 == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_258", + "id": "index_260", "file": "src/btree/index.rs", - "line": 258, + "line": 260, "decision": "frame.is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_284", + "id": "index_286", "file": "src/btree/index.rs", - "line": 284, + "line": 286, "decision": "match self.stack.len() {\n 0 => return Ok(None),\n n => n.saturating_sub(1),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_293", + "id": "index_295", "file": "src/btree/index.rs", - "line": 293, + "line": 295, "decision": "!is_interior", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_294", + "id": "index_296", "file": "src/btree/index.rs", - "line": 294, + "line": 296, "decision": "step == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_303", + "id": "index_305", "file": "src/btree/index.rs", - "line": 303, + "line": 305, "decision": "step == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_309", + "id": "index_311", "file": "src/btree/index.rs", - "line": 309, + "line": 311, "decision": "a % 2 == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_311", + "id": "index_313", "file": "src/btree/index.rs", - "line": 311, + "line": 313, "decision": "child_index == num_cells", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_415", + "id": "index_417", "file": "src/btree/index.rs", - "line": 415, + "line": 417, "decision": "match v {\n Value::Null => 0,\n Value::Integer(_) | Value::Real(_) => 1,\n Value::Text(_) => 2,\n Value::Blob(_) => 3,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_425", + "id": "index_427", "file": "src/btree/index.rs", - "line": 425, + "line": 427, "decision": "ra != rb", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_428", + "id": "index_430", "file": "src/btree/index.rs", - "line": 428, + "line": 430, "decision": "match (a, b) {\n (Value::Null, Value::Null) => Ordering::Equal,\n (Value::Integer(x), Value::Integer(y)) => x.cmp(y),\n (Value::Real(x), Value::Real(y)) => x.partial_cmp(y).unwrap_or(Ordering::Equal),\n (Value::Integer(x), Value::Real(y)) => {\n (*x as f64).partial_cmp(y).unwrap_or(Ordering::Equal)\n }\n (Value::Real(x), Value::Integer(y)) => {\n x.partial_cmp(&(*y as f64)).unwrap_or(Ordering::Equal)\n }\n (Value::Text(x), Value::Text(y)) => x.as_bytes().cmp(y.as_bytes()),\n (Value::Blob(x), Value::Blob(y)) => x.cmp(y),\n _ => Ordering::Equal, // unreachable: value_rank already separated these\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_449", + "id": "index_451", "file": "src/btree/index.rs", - "line": 449, + "line": 451, "decision": "c != Ordering::Equal", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_530", + "id": "index_532", "file": "src/btree/index.rs", - "line": 530, + "line": 532, "decision": "has_overflow", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_598", + "id": "index_600", "file": "src/btree/index.rs", - "line": 598, + "line": 600, "decision": "visited > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_608", + "id": "index_610", "file": "src/btree/index.rs", - "line": 608, + "line": 610, "decision": "page_type == LEAF_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_613", + "id": "index_615", "file": "src/btree/index.rs", - "line": 613, + "line": 615, "decision": "page_type == INTERIOR_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_639", + "id": "index_643", "file": "src/btree/index.rs", - "line": 639, + "line": 643, "decision": "compare_keys(key, entry_key) == Ordering::Less", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "index_712", + "id": "index_716", "file": "src/btree/index.rs", - "line": 712, + "line": 716, "decision": "match v {\n Value::Text(s) => s,\n other => panic!(\"expected text, got {other:?}\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_719", + "id": "index_723", "file": "src/btree/index.rs", - "line": 719, + "line": 723, "decision": "match v {\n Value::Integer(i) => *i,\n other => panic!(\"expected integer, got {other:?}\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "index_864", + "id": "index_868", "file": "src/btree/index.rs", - "line": 864, + "line": 868, "decision": "idx < expect_order.len() && text(&key[0]) == expect_order[idx]", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "index_885", + "id": "index_889", "file": "src/btree/index.rs", - "line": 885, + "line": 889, "decision": "match &row.payload {\n Payload::Local { page, .. } => {\n assert!(\n Rc::strong_count(page) >= 2,\n \"expected the row to share the page's Rc, not hold the only reference\"\n );\n }\n Payload::Owned(_) => panic!(\"expected a borrowed Local payload, got an Owned copy\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "master_120", + "id": "master_122", "file": "src/btree/master.rs", - "line": 120, + "line": 122, "decision": "s.as_ref() == key", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "master_224", + "id": "master_226", "file": "src/btree/master.rs", - "line": 224, + "line": 226, "decision": "n.as_ref() == name", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "master_229", + "id": "master_231", "file": "src/btree/master.rs", - "line": 229, + "line": 231, "decision": "rootpage == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "master_264", + "id": "master_266", "file": "src/btree/master.rs", - "line": 264, + "line": 266, "decision": "n.as_ref() == table_name", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "master_272", + "id": "master_274", "file": "src/btree/master.rs", - "line": 272, + "line": 274, "decision": "match existing {\n None => {\n let next_rowid = max_rowid(pager, header, seq_root)?\n .unwrap_or(0)\n .saturating_add(1);\n let values = [Value::Text(table_name.into()), Value::Integer(rowid)];\n let payload = encode_record(&values, header.text_encoding);\n super::insert_row(pager, header, seq_root, next_rowid, &payload)?;\n }\n Some((row_rowid, current_seq)) if rowid > current_seq => {\n super::delete_row(pager, header, seq_root, row_rowid)?;\n let values = [Value::Text(table_name.into()), Value::Integer(rowid)];\n let payload = encode_record(&values, header.text_encoding);\n super::insert_row(pager, header, seq_root, row_rowid, &payload)?;\n }\n Some(_) => {}\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "master_281", + "id": "master_283", "file": "src/btree/master.rs", - "line": 281, + "line": 283, "decision": "rowid > current_seq", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "master_348", + "id": "master_350", "file": "src/btree/master.rs", - "line": 348, + "line": 350, "decision": "tbl.as_ref() == table_name", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "master_373", + "id": "master_375", "file": "src/btree/master.rs", - "line": 373, + "line": 375, "decision": "match idx {\n Some(name) => Value::Text(name.into()),\n None => Value::Null,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "delete_62", + "id": "delete_61", "file": "src/btree/table/delete.rs", - "line": 62, - "decision": "cells.len() > 1 || ancestors.is_empty()", + "line": 61, + "decision": "num_cells > 1 || ancestors.is_empty()", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "delete_90", + "id": "delete_86", "file": "src/btree/table/delete.rs", - "line": 90, - "decision": "(local_size as u64) >= payload_len", - "conditions": 1, - "vectors_required": 2, - "compiler_void": false - }, - { - "id": "delete_105", - "file": "src/btree/table/delete.rs", - "line": 105, + "line": 86, "decision": "page_num != 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_106", + "id": "delete_87", "file": "src/btree/table/delete.rs", - "line": 106, + "line": 87, "decision": "!visited.insert(page_num)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_143", + "id": "delete_129", "file": "src/btree/table/delete.rs", - "line": 143, + "line": 129, "decision": "match entries.iter().position(|(child, _)| *child == emptied_page) {\n Some(idx) => {\n entries.remove(idx);\n }\n None if rightmost == emptied_page => {\n let Some((last_child, _)) = entries.pop() else {\n return Err(BtreeError::Internal(\n \"interior page's rightmost pointer was emptied but it has no routing entries to promote\",\n ));\n };\n rightmost = last_child;\n }\n None => {\n return Err(BtreeError::MissingChildRoute {\n page_num: parent_page,\n child: emptied_page,\n });\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "delete_147", + "id": "delete_133", "file": "src/btree/table/delete.rs", - "line": 147, + "line": 133, "decision": "rightmost == emptied_page", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_163", + "id": "delete_149", "file": "src/btree/table/delete.rs", - "line": 163, + "line": 149, "decision": "!entries.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_184", + "id": "delete_170", "file": "src/btree/table/delete.rs", - "line": 184, + "line": 170, "decision": "parent_page == root_page", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_214", + "id": "delete_202", "file": "src/btree/table/delete.rs", - "line": 214, + "line": 202, "decision": "match entries.iter_mut().find(|(child, _)| *child == old_child) {\n Some(entry) => entry.0 = new_child,\n None if rightmost == old_child => rightmost = new_child,\n None => {\n return Err(BtreeError::MissingChildRoute {\n page_num: parent_page,\n child: old_child,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "delete_216", + "id": "delete_204", "file": "src/btree/table/delete.rs", - "line": 216, + "line": 204, "decision": "rightmost == old_child", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_249", + "id": "delete_237", "file": "src/btree/table/delete.rs", - "line": 249, + "line": 237, "decision": "match page_type {\n LEAF_TABLE => {\n let cells = collect_leaf_cells(&content, child_header_start, only_child, usable_size)?;\n let dest = pager.get_page_mut(root_page)?;\n write_leaf_page(dest, root_header_start, root_page, &cell_bytes(cells))?;\n }\n INTERIOR_TABLE => {\n let (entries, rightmost) =\n collect_interior_entries(&content, child_header_start, only_child)?;\n let cells: Vec> = entries\n .iter()\n .map(|(child, key)| build_interior_cell(*child, *key))\n .collect();\n let dest = pager.get_page_mut(root_page)?;\n write_interior_page(dest, root_header_start, root_page, &cells, rightmost)?;\n }\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num: only_child,\n page_type: other,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "delete_530", + "id": "delete_518", "file": "src/btree/table/delete.rs", - "line": 530, + "line": 518, "decision": "page_type == LEAF_TABLE", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_76", + "id": "insert_79", "file": "src/btree/table/insert.rs", - "line": 76, + "line": 79, "decision": "!overflow_bytes.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_95", + "id": "insert_98", "file": "src/btree/table/insert.rs", - "line": 95, + "line": 98, "decision": "!rest.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_138", - "file": "src/btree/table/insert.rs", - "line": 138, - "decision": "*existing_rowid == rowid", - "conditions": 1, - "vectors_required": 2, - "compiler_void": false - }, - { - "id": "insert_141", - "file": "src/btree/table/insert.rs", - "line": 141, - "decision": "*existing_rowid > rowid", - "conditions": 1, - "vectors_required": 2, - "compiler_void": false - }, - { - "id": "insert_154", + "id": "insert_150", "file": "src/btree/table/insert.rs", - "line": 154, + "line": 150, "decision": "needed <= page_len", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_160", + "id": "insert_155", "file": "src/btree/table/insert.rs", - "line": 160, + "line": 155, "decision": "!splice_insert_cell(buf, header_start, leaf_page, insert_pos, &cell)?", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_224", + "id": "insert_228", "file": "src/btree/table/insert.rs", - "line": 224, + "line": 228, "decision": "match entries.iter().position(|(child, _)| *child == old_page) {\n Some(idx) => {\n entries.insert(idx, (old_page, divider));\n let successor = entries\n .get_mut(idx.saturating_add(1))\n .ok_or(BtreeError::Internal(\n \"split successor entry must exist right after insertion\",\n ))?;\n successor.0 = new_page;\n }\n None if rightmost == old_page => {\n entries.push((old_page, divider));\n rightmost = new_page;\n }\n None => {\n return Err(BtreeError::MissingChildRoute {\n page_num: parent_page,\n child: old_page,\n });\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "insert_234", + "id": "insert_238", "file": "src/btree/table/insert.rs", - "line": 234, + "line": 238, "decision": "rightmost == old_page", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_256", + "id": "insert_260", "file": "src/btree/table/insert.rs", - "line": 256, + "line": 260, "decision": "needed <= page_len", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_325", + "id": "insert_329", "file": "src/btree/table/insert.rs", - "line": 325, + "line": 329, "decision": "match page_type {\n LEAF_TABLE => {\n let cells = collect_leaf_cells(&content, header_start_root, root_page, usable_size)?;\n let dest = pager.get_page_mut(relocated)?;\n write_leaf_page(dest, 0, relocated, &cell_bytes(cells))?;\n }\n INTERIOR_TABLE => {\n let (entries, rightmost) =\n collect_interior_entries(&content, header_start_root, root_page)?;\n let cells: Vec> = entries\n .iter()\n .map(|(child, key)| build_interior_cell(*child, *key))\n .collect();\n let dest = pager.get_page_mut(relocated)?;\n write_interior_page(dest, 0, relocated, &cells, rightmost)?;\n }\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num: root_page,\n page_type: other,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "insert_385", + "id": "insert_389", "file": "src/btree/table/insert.rs", - "line": 385, + "line": 389, "decision": "page_type == LEAF_TABLE", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_65", + "id": "delete_67", "file": "src/btree/index/delete.rs", - "line": 65, + "line": 67, "decision": "match descend_index_tree(pager, root_page, usable_size, key, encoding)? {\n IndexDescent::Leaf { leaf_page, .. } => {\n delete_from_leaf(pager, usable_size, leaf_page, key, encoding)\n }\n IndexDescent::InteriorMatch {\n interior_page,\n entry_child,\n } => delete_via_predecessor_swap(pager, usable_size, interior_page, entry_child, encoding),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "delete_110", + "id": "delete_112", "file": "src/btree/index/delete.rs", - "line": 110, + "line": 112, "decision": "match extract_max_entry(pager, usable_size, entry_child, encoding, 0)? {\n Some(predecessor_bytes) => {\n let header_start = page1_header_start(interior_page);\n let buf = pager.get_page_mut(interior_page)?.clone();\n let (mut entries, rightmost) = collect_index_interior_entries(\n pager,\n &buf,\n header_start,\n interior_page,\n usable_size,\n encoding,\n )?;\n let entry = entries\n .iter_mut()\n .find(|(child, _, _)| *child == entry_child)\n .ok_or(BtreeError::Internal(\n \"entry_child's routing entry must still exist in interior_page\",\n ))?;\n entry.2 = predecessor_bytes;\n let cell_bytes: Vec> = entries\n .iter()\n .map(|(child, _, value_bytes)| build_index_interior_cell(*child, value_bytes))\n .collect();\n let buf = pager.get_page_mut(interior_page)?;\n write_index_interior_page(buf, header_start, interior_page, &cell_bytes, rightmost)\n }\n None => {\n // `entry_child`'s entire subtree is drained (nothing left to\n // swap in) — the matched entry is deleted outright, since\n // there is nothing left to preserve.\n pager.deallocate_page(entry_child)?;\n remove_entry_by_child(pager, usable_size, interior_page, entry_child, encoding)\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "delete_169", + "id": "delete_171", "file": "src/btree/index/delete.rs", - "line": 169, + "line": 171, "decision": "depth > MAX_PAGES_VISITED", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_178", + "id": "delete_180", "file": "src/btree/index/delete.rs", - "line": 178, + "line": 180, "decision": "page_type == LEAF_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_189", + "id": "delete_191", "file": "src/btree/index/delete.rs", - "line": 189, + "line": 191, "decision": "page_type != INTERIOR_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_425", + "id": "delete_427", "file": "src/btree/index/delete.rs", - "line": 425, + "line": 427, "decision": "page_type != INTERIOR_INDEX", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "delete_449", + "id": "delete_451", "file": "src/btree/index/delete.rs", - "line": 449, + "line": 451, "decision": "trunk != 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_49", + "id": "insert_51", "file": "src/btree/index/insert.rs", - "line": 49, + "line": 51, "decision": "match descend_index_tree(pager, root_page, usable_size, key, encoding)? {\n IndexDescent::Leaf {\n ancestors,\n leaf_page,\n } => (ancestors, leaf_page),\n IndexDescent::InteriorMatch { .. } => return Err(BtreeError::DuplicateKey),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "insert_91", + "id": "insert_93", "file": "src/btree/index/insert.rs", - "line": 91, + "line": 93, "decision": "!overflow_bytes.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_110", + "id": "insert_112", "file": "src/btree/index/insert.rs", - "line": 110, + "line": 112, "decision": "!rest.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_156", + "id": "insert_158", "file": "src/btree/index/insert.rs", - "line": 156, + "line": 158, "decision": "match compare_keys(key, existing_key) {\n std::cmp::Ordering::Equal => return Err(BtreeError::DuplicateKey),\n std::cmp::Ordering::Less => {\n insert_pos = i;\n break;\n }\n std::cmp::Ordering::Greater => {}\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "insert_175", + "id": "insert_177", "file": "src/btree/index/insert.rs", - "line": 175, + "line": 177, "decision": "needed <= page_len", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_180", + "id": "insert_182", "file": "src/btree/index/insert.rs", - "line": 180, + "line": 182, "decision": "!splice_insert_cell(buf, header_start, leaf_page, insert_pos, &cell)?", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_261", + "id": "insert_263", "file": "src/btree/index/insert.rs", - "line": 261, + "line": 263, "decision": "match entries.iter().position(|(child, _, _)| *child == old_page) {\n Some(idx) => {\n entries.insert(idx, (old_page, promoted_key.to_vec(), promoted_bytes));\n let successor = entries\n .get_mut(idx.saturating_add(1))\n .ok_or(BtreeError::Internal(\n \"split successor entry must exist right after insertion\",\n ))?;\n successor.0 = new_page;\n }\n None if rightmost == old_page => {\n entries.push((old_page, promoted_key.to_vec(), promoted_bytes));\n rightmost = new_page;\n }\n None => {\n return Err(BtreeError::MissingChildRoute {\n page_num: parent_page,\n child: old_page,\n });\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "insert_271", + "id": "insert_273", "file": "src/btree/index/insert.rs", - "line": 271, + "line": 273, "decision": "rightmost == old_page", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_293", + "id": "insert_295", "file": "src/btree/index/insert.rs", - "line": 293, + "line": 295, "decision": "needed <= page_len", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "insert_365", + "id": "insert_367", "file": "src/btree/index/insert.rs", - "line": 365, + "line": 367, "decision": "match page_type {\n LEAF_INDEX => {\n let cells = collect_index_leaf_cells(\n pager,\n &content,\n header_start_root,\n root_page,\n usable_size,\n encoding,\n )?;\n let dest = pager.get_page_mut(relocated)?;\n write_index_leaf_page(dest, 0, relocated, &cell_bytes(cells))?;\n }\n INTERIOR_INDEX => {\n let (entries, rightmost) = collect_index_interior_entries(\n pager,\n &content,\n header_start_root,\n root_page,\n usable_size,\n encoding,\n )?;\n let cells: Vec> = entries\n .iter()\n .map(|(child, _, value_bytes)| build_index_interior_cell(*child, value_bytes))\n .collect();\n let dest = pager.get_page_mut(relocated)?;\n write_index_interior_page(dest, 0, relocated, &cells, rightmost)?;\n }\n other => {\n return Err(BtreeError::UnexpectedPageType {\n page_num: root_page,\n page_type: other,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "insert_520", + "id": "insert_522", "file": "src/btree/index/insert.rs", - "line": 520, + "line": 522, "decision": "match &k[0] {\n Value::Text(s) => s.as_ref(),\n _ => panic!(\"expected text\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_52", + "id": "functions_54", "file": "src/vdbe/functions.rs", - "line": 52, + "line": 54, "decision": "match self {\n FunctionError::Unknown { name, arity } => {\n write!(f, \"unknown function {name} with {arity} argument(s)\")\n }\n FunctionError::WrongArity { name } => {\n write!(f, \"wrong number of arguments to function {name}()\")\n }\n FunctionError::IntegerOverflow => write!(f, \"integer overflow\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_70", + "id": "functions_72", "file": "src/vdbe/functions.rs", - "line": 70, + "line": 72, "decision": "match v {\n Value::Null => String::new(),\n Value::Integer(i) => i.to_string(),\n Value::Real(r) => format_real(*r),\n Value::Text(s) => s.to_string(),\n Value::Blob(b) => String::from_utf8_lossy(b).into_owned(),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_80", + "id": "functions_82", "file": "src/vdbe/functions.rs", - "line": 80, + "line": 82, "decision": "match &args[0] {\n Value::Null => Value::Null,\n Value::Blob(b) => Value::Integer(b.len() as i64),\n Value::Text(s) => Value::Integer(s.chars().count() as i64),\n other => Value::Integer(as_text(other).chars().count() as i64),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_89", + "id": "functions_91", "file": "src/vdbe/functions.rs", - "line": 89, + "line": 91, "decision": "match &args[0] {\n Value::Null => Value::Null,\n Value::Text(s) => Value::Text(s.to_ascii_uppercase().into()),\n other => other.clone(),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_97", + "id": "functions_99", "file": "src/vdbe/functions.rs", - "line": 97, + "line": 99, "decision": "match &args[0] {\n Value::Null => Value::Null,\n Value::Text(s) => Value::Text(s.to_ascii_lowercase().into()),\n other => other.clone(),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_106", + "id": "functions_108", "file": "src/vdbe/functions.rs", - "line": 106, + "line": 108, "decision": "match v {\n Value::Integer(i) => *i,\n Value::Real(r) => *r as i64,\n Value::Text(_) => crate::vdbe::coerce::cast_to_integer(v),\n Value::Null | Value::Blob(_) => 0,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_119", + "id": "functions_121", "file": "src/vdbe/functions.rs", - "line": 119, + "line": 121, "decision": "matches!(args[1], Value::Null) || args.get(2).is_some_and(|v| matches!(v, Value::Null))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_122", + "id": "functions_124", "file": "src/vdbe/functions.rs", - "line": 122, + "line": 124, "decision": "matches!(args[0], Value::Null)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_126", + "id": "functions_128", "file": "src/vdbe/functions.rs", - "line": 126, + "line": 128, "decision": "match args.get(2) {\n Some(z) => {\n let raw = value_int(z);\n if raw < 0 {\n (raw.saturating_neg(), true)\n } else {\n (raw, false)\n }\n }\n None => (i64::MAX / 2, false),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_129", + "id": "functions_131", "file": "src/vdbe/functions.rs", - "line": 129, + "line": 131, "decision": "raw < 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_138", + "id": "functions_140", "file": "src/vdbe/functions.rs", - "line": 138, + "line": 140, "decision": "match &args[0] {\n Value::Blob(b) => Some(b),\n _ => None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_144", + "id": "functions_146", "file": "src/vdbe/functions.rs", - "line": 144, + "line": 146, "decision": "p1 < 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_150", + "id": "functions_152", "file": "src/vdbe/functions.rs", - "line": 150, + "line": 152, "decision": "p1 < 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_152", + "id": "functions_154", "file": "src/vdbe/functions.rs", - "line": 152, + "line": 154, "decision": "p1 < 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_154", + "id": "functions_156", "file": "src/vdbe/functions.rs", - "line": 154, + "line": 156, "decision": "p2 < 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_159", + "id": "functions_161", "file": "src/vdbe/functions.rs", - "line": 159, + "line": 161, "decision": "p1 > 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_161", + "id": "functions_163", "file": "src/vdbe/functions.rs", - "line": 161, + "line": 163, "decision": "p2 > 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_165", + "id": "functions_167", "file": "src/vdbe/functions.rs", - "line": 165, + "line": 167, "decision": "neg_p2", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_167", + "id": "functions_169", "file": "src/vdbe/functions.rs", - "line": 167, + "line": 169, "decision": "p1 < 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_196", + "id": "functions_198", "file": "src/vdbe/functions.rs", - "line": 196, + "line": 198, "decision": "match &args[0] {\n Value::Null => Value::Null,\n Value::Integer(i) => Value::Integer(i.checked_abs().ok_or(FunctionError::IntegerOverflow)?),\n Value::Real(r) => Value::Real(r.abs()),\n // Text/blob arguments always coerce through the REAL path — even\n // a clean integer-looking string like '5' yields REAL 5.0, per\n // the oracle (abs() does not attempt the INTEGER-preserving path\n // for non-numeric-typed inputs).\n other => Value::Real(value_f64(other).abs()),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_218", + "id": "functions_220", "file": "src/vdbe/functions.rs", - "line": 218, + "line": 220, "decision": "matches!(a, Value::Null) || matches!(b, Value::Null)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_221", + "id": "functions_223", "file": "src/vdbe/functions.rs", - "line": 221, + "line": 223, "decision": "compare(a, b, Collation::Binary) == Ordering::Equal", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_229", + "id": "functions_231", "file": "src/vdbe/functions.rs", - "line": 229, + "line": 231, "decision": "match &args[0] {\n Value::Null => \"null\",\n Value::Integer(_) => \"integer\",\n Value::Real(_) => \"real\",\n Value::Text(_) => \"text\",\n Value::Blob(_) => \"blob\",\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_240", + "id": "functions_242", "file": "src/vdbe/functions.rs", - "line": 240, + "line": 242, "decision": "match &args[0] {\n Value::Blob(b) => b.to_vec(),\n other => as_text(other).into_bytes(),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_252", + "id": "functions_254", "file": "src/vdbe/functions.rs", - "line": 252, + "line": 254, "decision": "match c {\n b'0'..=b'9' => Some(c.saturating_sub(b'0')),\n b'a'..=b'f' => Some(c.saturating_sub(b'a').saturating_add(10)),\n b'A'..=b'F' => Some(c.saturating_sub(b'A').saturating_add(10)),\n _ => None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_261", + "id": "functions_263", "file": "src/vdbe/functions.rs", - "line": 261, + "line": 263, "decision": "matches!(args[0], Value::Null)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_266", + "id": "functions_268", "file": "src/vdbe/functions.rs", - "line": 266, + "line": 268, "decision": "!bytes.len().is_multiple_of(2)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_283", + "id": "functions_285", "file": "src/vdbe/functions.rs", - "line": 283, + "line": 285, "decision": "c == '\\''", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_293", + "id": "functions_295", "file": "src/vdbe/functions.rs", - "line": 293, + "line": 295, "decision": "match &args[0] {\n Value::Null => \"NULL\".to_string().into(),\n Value::Integer(i) => i.to_string().into(),\n Value::Real(r) => format_real(*r).into(),\n Value::Text(s) => sql_quote_text(s).into(),\n Value::Blob(b) => format_blob(b).into(),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_303", + "id": "functions_305", "file": "src/vdbe/functions.rs", - "line": 303, + "line": 305, "decision": "args.iter().any(|v| matches!(v, Value::Null))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_314", + "id": "functions_316", "file": "src/vdbe/functions.rs", - "line": 314, + "line": 316, "decision": "args.iter().any(|v| matches!(v, Value::Null))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_325", + "id": "functions_327", "file": "src/vdbe/functions.rs", - "line": 325, + "line": 327, "decision": "match v {\n Value::Integer(i) => *i as f64,\n Value::Real(r) => *r,\n Value::Text(s) => match crate::vdbe::coerce::coerce_text_to_numeric(s) {\n Value::Integer(i) => i as f64,\n Value::Real(r) => r,\n _ => 0.0,\n },\n Value::Null | Value::Blob(_) => 0.0,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_328", + "id": "functions_330", "file": "src/vdbe/functions.rs", - "line": 328, + "line": 330, "decision": "match crate::vdbe::coerce::coerce_text_to_numeric(s) {\n Value::Integer(i) => i as f64,\n Value::Real(r) => r,\n _ => 0.0,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_341", + "id": "functions_343", "file": "src/vdbe/functions.rs", - "line": 341, + "line": 343, "decision": "matches!(args[0], Value::Null) || matches!(args.get(1), Some(Value::Null))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_349", + "id": "functions_351", "file": "src/vdbe/functions.rs", - "line": 349, + "line": 351, "decision": "scaled >= 0.0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_358", + "id": "functions_360", "file": "src/vdbe/functions.rs", - "line": 358, + "line": 360, "decision": "match &args[0] {\n Value::Null => Value::Null,\n other => {\n let n = value_f64(other);\n Value::Integer(if n > 0.0 {\n 1\n } else if n < 0.0 {\n -1\n } else {\n 0\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_362", + "id": "functions_364", "file": "src/vdbe/functions.rs", - "line": 362, + "line": 364, "decision": "n > 0.0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_364", + "id": "functions_366", "file": "src/vdbe/functions.rs", - "line": 364, + "line": 366, "decision": "n < 0.0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_374", + "id": "functions_376", "file": "src/vdbe/functions.rs", - "line": 374, + "line": 376, "decision": "matches!(args[0], Value::Null) || matches!(args[1], Value::Null)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_378", + "id": "functions_380", "file": "src/vdbe/functions.rs", - "line": 378, + "line": 380, "decision": "match &args[1] {\n Value::Blob(b) => find_bytes(hay, b),\n other => find_bytes(hay, as_text(other).as_bytes()),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_397", + "id": "functions_399", "file": "src/vdbe/functions.rs", - "line": 397, + "line": 399, "decision": "needle.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_408", + "id": "functions_410", "file": "src/vdbe/functions.rs", - "line": 408, + "line": 410, "decision": "matches!(args[0], Value::Null)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_419", + "id": "functions_421", "file": "src/vdbe/functions.rs", - "line": 419, + "line": 421, "decision": "matches!(args[0], Value::Null)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_432", + "id": "functions_434", "file": "src/vdbe/functions.rs", - "line": 432, + "line": 434, "decision": "matches!(args[0], Value::Null)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_445", + "id": "functions_447", "file": "src/vdbe/functions.rs", - "line": 445, + "line": 447, "decision": "args.iter().any(|v| matches!(v, Value::Null))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_451", + "id": "functions_453", "file": "src/vdbe/functions.rs", - "line": 451, + "line": 453, "decision": "from.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_469", + "id": "functions_471", "file": "src/vdbe/functions.rs", - "line": 469, + "line": 471, "decision": "match &args[0] {\n Value::Null => false,\n Value::Integer(i) => *i != 0,\n Value::Real(r) => *r != 0.0,\n Value::Text(s) => match crate::vdbe::coerce::coerce_text_to_numeric(s) {\n Value::Integer(i) => i != 0,\n Value::Real(r) => r != 0.0,\n _ => false,\n },\n Value::Blob(_) => false,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_473", + "id": "functions_475", "file": "src/vdbe/functions.rs", - "line": 473, + "line": 475, "decision": "match crate::vdbe::coerce::coerce_text_to_numeric(s) {\n Value::Integer(i) => i != 0,\n Value::Real(r) => r != 0.0,\n _ => false,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_480", + "id": "functions_482", "file": "src/vdbe/functions.rs", - "line": 480, + "line": 482, "decision": "cond", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_498", + "id": "functions_500", "file": "src/vdbe/functions.rs", - "line": 498, + "line": 500, "decision": "pi == p.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_502", + "id": "functions_504", "file": "src/vdbe/functions.rs", - "line": 502, + "line": 504, "decision": "Some(pc) == escape && pi.saturating_add(1) < p.len()", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_504", + "id": "functions_506", "file": "src/vdbe/functions.rs", - "line": 504, + "line": 506, "decision": "ti >= t.len() || !ascii_eq(t[ti], literal)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_511", + "id": "functions_513", "file": "src/vdbe/functions.rs", - "line": 511, + "line": 513, "decision": "match pc {\n '%' => {\n // Collapse consecutive '%' (a run behaves as one).\n while pi < p.len() && p[pi] == '%' {\n pi = pi.saturating_add(1);\n }\n if pi == p.len() {\n return true;\n }\n for start in ti..=t.len() {\n if like_rec(t, p, escape, start, pi) {\n return true;\n }\n }\n return false;\n }\n '_' => {\n if ti >= t.len() {\n return false;\n }\n ti = ti.saturating_add(1);\n pi = pi.saturating_add(1);\n }\n _ => {\n if ti >= t.len() || !ascii_eq(t[ti], pc) {\n return false;\n }\n ti = ti.saturating_add(1);\n pi = pi.saturating_add(1);\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_514", + "id": "functions_516", "file": "src/vdbe/functions.rs", - "line": 514, + "line": 516, "decision": "pi < p.len() && p[pi] == '%'", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_517", + "id": "functions_519", "file": "src/vdbe/functions.rs", - "line": 517, + "line": 519, "decision": "pi == p.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_521", + "id": "functions_523", "file": "src/vdbe/functions.rs", - "line": 521, + "line": 523, "decision": "like_rec(t, p, escape, start, pi)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_528", + "id": "functions_530", "file": "src/vdbe/functions.rs", - "line": 528, + "line": 530, "decision": "ti >= t.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_535", + "id": "functions_537", "file": "src/vdbe/functions.rs", - "line": 535, + "line": 537, "decision": "ti >= t.len() || !ascii_eq(t[ti], pc)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_559", + "id": "functions_561", "file": "src/vdbe/functions.rs", - "line": 559, + "line": 561, "decision": "pi == p.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_562", + "id": "functions_564", "file": "src/vdbe/functions.rs", - "line": 562, + "line": 564, "decision": "match p[pi] {\n '*' => {\n while pi < p.len() && p[pi] == '*' {\n pi = pi.saturating_add(1);\n }\n if pi == p.len() {\n return true;\n }\n for start in ti..=t.len() {\n if glob_rec(t, p, start, pi) {\n return true;\n }\n }\n return false;\n }\n '?' => {\n if ti >= t.len() {\n return false;\n }\n ti = ti.saturating_add(1);\n pi = pi.saturating_add(1);\n }\n '[' => {\n let Some((matches, next_pi)) = glob_class(p, pi, t.get(ti).copied()) else {\n return false;\n };\n if ti >= t.len() || !matches {\n return false;\n }\n ti = ti.saturating_add(1);\n pi = next_pi;\n }\n c => {\n if ti >= t.len() || t[ti] != c {\n return false;\n }\n ti = ti.saturating_add(1);\n pi = pi.saturating_add(1);\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_564", + "id": "functions_566", "file": "src/vdbe/functions.rs", - "line": 564, + "line": 566, "decision": "pi < p.len() && p[pi] == '*'", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_567", + "id": "functions_569", "file": "src/vdbe/functions.rs", - "line": 567, + "line": 569, "decision": "pi == p.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_571", + "id": "functions_573", "file": "src/vdbe/functions.rs", - "line": 571, + "line": 573, "decision": "glob_rec(t, p, start, pi)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_578", + "id": "functions_580", "file": "src/vdbe/functions.rs", - "line": 578, + "line": 580, "decision": "ti >= t.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_588", + "id": "functions_590", "file": "src/vdbe/functions.rs", - "line": 588, + "line": 590, "decision": "ti >= t.len() || !matches", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_595", + "id": "functions_597", "file": "src/vdbe/functions.rs", - "line": 595, + "line": 597, "decision": "ti >= t.len() || t[ti] != c", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_610", + "id": "functions_612", "file": "src/vdbe/functions.rs", - "line": 610, + "line": 612, "decision": "negate", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_616", + "id": "functions_618", "file": "src/vdbe/functions.rs", - "line": 616, + "line": 618, "decision": "i >= p.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_619", + "id": "functions_621", "file": "src/vdbe/functions.rs", - "line": 619, + "line": 621, "decision": "p[i] == ']' && i > class_start", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_623", + "id": "functions_625", "file": "src/vdbe/functions.rs", - "line": 623, + "line": 625, "decision": "i.saturating_add(2) < p.len()\n && p[i.saturating_add(1)] == '-'\n && p[i.saturating_add(2)] != ']'", "conditions": 3, "vectors_required": 4, "compiler_void": false }, { - "id": "functions_629", + "id": "functions_631", "file": "src/vdbe/functions.rs", - "line": 629, + "line": 631, "decision": "c >= lo && c <= hi", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "functions_635", + "id": "functions_637", "file": "src/vdbe/functions.rs", - "line": 635, + "line": 637, "decision": "Some(p[i]) == c", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_647", + "id": "functions_649", "file": "src/vdbe/functions.rs", - "line": 647, + "line": 649, "decision": "args.iter().any(|v| matches!(v, Value::Null))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_650", + "id": "functions_652", "file": "src/vdbe/functions.rs", - "line": 650, + "line": 652, "decision": "match args.get(2) {\n Some(e) => as_text(e).chars().next(),\n None => None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_663", + "id": "functions_665", "file": "src/vdbe/functions.rs", - "line": 663, + "line": 665, "decision": "args.iter().any(|v| matches!(v, Value::Null))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_677", + "id": "functions_679", "file": "src/vdbe/functions.rs", - "line": 677, + "line": 679, "decision": "match (name.to_ascii_lowercase().as_str(), arity) {\n (\"length\", 1) => Some(length),\n (\"upper\", 1) => Some(upper),\n (\"lower\", 1) => Some(lower),\n (\"substr\", 2 | 3) => Some(substr),\n (\"sqlite_version\", 0) => Some(sqlite_version),\n (\"abs\", 1) => Some(abs),\n (\"coalesce\", n) if n >= 2 => Some(coalesce),\n (\"ifnull\", 2) => Some(coalesce),\n (\"nullif\", 2) => Some(nullif),\n (\"typeof\", 1) => Some(typeof_fn),\n (\"hex\", 1) => Some(hex),\n (\"unhex\", 1) => Some(unhex),\n (\"quote\", 1) => Some(quote),\n (\"min\", n) if n >= 1 => Some(scalar_min),\n (\"max\", n) if n >= 1 => Some(scalar_max),\n (\"round\", 1 | 2) => Some(round_fn),\n (\"sign\", 1) => Some(sign),\n (\"instr\", 2) => Some(instr),\n (\"trim\", 1 | 2) => Some(trim_fn),\n (\"ltrim\", 1 | 2) => Some(ltrim_fn),\n (\"rtrim\", 1 | 2) => Some(rtrim_fn),\n (\"replace\", 3) => Some(replace_fn),\n (\"zeroblob\", 1) => Some(zeroblob),\n (\"iif\", 3) => Some(iif),\n (\"like\", 2 | 3) => Some(like_fn),\n (\"glob\", 2) => Some(glob_fn),\n _ => None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "functions_684", + "id": "functions_686", "file": "src/vdbe/functions.rs", - "line": 684, + "line": 686, "decision": "n >= 2", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_691", + "id": "functions_693", "file": "src/vdbe/functions.rs", - "line": 691, + "line": 693, "decision": "n >= 1", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_692", + "id": "functions_694", "file": "src/vdbe/functions.rs", - "line": 692, + "line": 694, "decision": "n >= 1", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "functions_706", + "id": "functions_708", "file": "src/vdbe/functions.rs", - "line": 706, + "line": 708, "decision": "match f {\n Some(f) => f(args),\n None => Err(FunctionError::Unknown {\n name: name.to_string(),\n arity,\n }),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_69", + "id": "grammar_71", "file": "src/parser/grammar.rs", - "line": 69, + "line": 71, "decision": "self.depth > MAX_EXPR_DEPTH", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_105", + "id": "grammar_107", "file": "src/parser/grammar.rs", - "line": 105, + "line": 107, "decision": "!matches!(tok.kind, TokenKind::Eof)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_116", + "id": "grammar_121", "file": "src/parser/grammar.rs", - "line": 116, + "line": 121, + "decision": "!matches!(self.peek().kind, TokenKind::Eof)", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "grammar_132", + "file": "src/parser/grammar.rs", + "line": 132, "decision": "self.at_kw(kw)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_125", + "id": "grammar_141", "file": "src/parser/grammar.rs", - "line": 125, + "line": 141, "decision": "self.at_kw(kw)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_137", + "id": "grammar_153", "file": "src/parser/grammar.rs", - "line": 137, + "line": 153, "decision": "&self.peek().kind == kind", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_146", + "id": "grammar_162", "file": "src/parser/grammar.rs", - "line": 146, + "line": 162, "decision": "self.peek().kind == kind", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_174", + "id": "grammar_190", "file": "src/parser/grammar.rs", - "line": 174, + "line": 190, "decision": "self.eat_punct(&TokenKind::Semicolon)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_175", + "id": "grammar_191", "file": "src/parser/grammar.rs", - "line": 175, + "line": 191, "decision": "match &self.peek().kind {\n TokenKind::Eof => Ok(()),\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT) => {\n self.unsupported(\"compound SELECT (UNION/INTERSECT/EXCEPT) not yet supported\")\n }\n other => {\n let tok = other.clone();\n Err(ParseFail::Invalid {\n message: format!(\"unexpected trailing token {tok:?}\"),\n span: self.peek().span,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_193", + "id": "grammar_209", "file": "src/parser/grammar.rs", - "line": 193, - "decision": "match self.peek().kind.clone() {\n TokenKind::Identifier(name) => {\n let span = self.advance().span;\n Ok((name, span))\n }\n _ => {\n let tok = self.peek().clone();\n Err(ParseFail::Invalid {\n message: format!(\"expected identifier, found {:?}\", tok.kind),\n span: tok.span,\n })\n }\n }", + "line": 209, + "decision": "match self.peek().kind.clone() {\n TokenKind::Identifier(name) => {\n let span = self.advance_span();\n Ok((name, span))\n }\n _ => {\n let tok = self.peek().clone();\n Err(ParseFail::Invalid {\n message: format!(\"expected identifier, found {:?}\", tok.kind),\n span: tok.span,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_212", + "id": "grammar_228", "file": "src/parser/grammar.rs", - "line": 212, + "line": 228, "decision": "self.eat_kw(Keyword::OR)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_220", + "id": "grammar_236", "file": "src/parser/grammar.rs", - "line": 220, + "line": 236, "decision": "self.eat_punct(&TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_222", + "id": "grammar_238", "file": "src/parser/grammar.rs", - "line": 222, + "line": 238, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_231", + "id": "grammar_247", "file": "src/parser/grammar.rs", - "line": 231, + "line": 247, "decision": "self.eat_kw(Keyword::DEFAULT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_234", + "id": "grammar_250", "file": "src/parser/grammar.rs", - "line": 234, + "line": 250, "decision": "self.eat_kw(Keyword::VALUES)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_238", + "id": "grammar_254", "file": "src/parser/grammar.rs", - "line": 238, + "line": 254, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_246", + "id": "grammar_262", "file": "src/parser/grammar.rs", - "line": 246, + "line": 262, "decision": "self.at_kw(Keyword::SELECT) || self.at_kw(Keyword::WITH)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_269", + "id": "grammar_285", "file": "src/parser/grammar.rs", - "line": 269, + "line": 285, "decision": "self.eat_kw(Keyword::WHERE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_285", + "id": "grammar_301", "file": "src/parser/grammar.rs", - "line": 285, + "line": 301, "decision": "self.eat_kw(Keyword::REPLACE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_287", + "id": "grammar_303", "file": "src/parser/grammar.rs", - "line": 287, + "line": 303, "decision": "self.eat_kw(Keyword::IGNORE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_289", + "id": "grammar_305", "file": "src/parser/grammar.rs", - "line": 289, + "line": 305, "decision": "self.eat_kw(Keyword::ABORT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_291", + "id": "grammar_307", "file": "src/parser/grammar.rs", - "line": 291, + "line": 307, "decision": "self.eat_kw(Keyword::ROLLBACK)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_293", + "id": "grammar_309", "file": "src/parser/grammar.rs", - "line": 293, + "line": 309, "decision": "self.eat_kw(Keyword::FAIL)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_314", + "id": "grammar_330", "file": "src/parser/grammar.rs", - "line": 314, + "line": 330, "decision": "self.eat_kw(Keyword::OR)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_325", + "id": "grammar_341", "file": "src/parser/grammar.rs", - "line": 325, + "line": 341, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_329", + "id": "grammar_345", "file": "src/parser/grammar.rs", - "line": 329, + "line": 345, "decision": "self.eat_kw(Keyword::WHERE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_355", + "id": "grammar_371", "file": "src/parser/grammar.rs", - "line": 355, + "line": 371, "decision": "matches!(self.peek().kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_358", + "id": "grammar_374", "file": "src/parser/grammar.rs", - "line": 358, + "line": 374, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_363", + "id": "grammar_379", "file": "src/parser/grammar.rs", - "line": 363, + "line": 379, "decision": "!matches!(self.peek().kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_367", + "id": "grammar_383", "file": "src/parser/grammar.rs", - "line": 367, + "line": 383, "decision": "self.at_kw(Keyword::SELECT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_372", + "id": "grammar_388", "file": "src/parser/grammar.rs", - "line": 372, + "line": 388, "decision": "values.len() != columns.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_397", + "id": "grammar_413", "file": "src/parser/grammar.rs", - "line": 397, + "line": 413, "decision": "self.eat_kw(Keyword::IF)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_407", + "id": "grammar_423", "file": "src/parser/grammar.rs", - "line": 407, + "line": 423, "decision": "self.eat_kw(Keyword::IF)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_419", + "id": "grammar_435", "file": "src/parser/grammar.rs", - "line": 419, + "line": 435, "decision": "matches!(&self.peek().kind, TokenKind::Identifier(id) if id.eq_ignore_ascii_case(word))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_430", + "id": "grammar_446", "file": "src/parser/grammar.rs", - "line": 430, + "line": 446, "decision": "matches!(self.peek().kind, TokenKind::Dot)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_440", + "id": "grammar_456", "file": "src/parser/grammar.rs", - "line": 440, + "line": 456, "decision": "self.at_kw(Keyword::ON)\n && matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::CONFLICT))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_450", + "id": "grammar_466", "file": "src/parser/grammar.rs", - "line": 450, + "line": 466, "decision": "self.at_kw(Keyword::TEMP) || self.at_kw(Keyword::TEMPORARY)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_453", + "id": "grammar_469", "file": "src/parser/grammar.rs", - "line": 453, + "line": 469, "decision": "self.at_kw(Keyword::VIRTUAL)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_460", + "id": "grammar_476", "file": "src/parser/grammar.rs", - "line": 460, + "line": 476, "decision": "self.at_kw(Keyword::AS)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_467", + "id": "grammar_483", "file": "src/parser/grammar.rs", - "line": 467, + "line": 483, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_468", + "id": "grammar_484", "file": "src/parser/grammar.rs", - "line": 468, + "line": 484, "decision": "self.at_table_constraint_start()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_470", + "id": "grammar_486", "file": "src/parser/grammar.rs", - "line": 470, + "line": 486, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_481", + "id": "grammar_497", "file": "src/parser/grammar.rs", - "line": 481, + "line": 497, "decision": "self.eat_kw(Keyword::WITHOUT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_482", + "id": "grammar_498", "file": "src/parser/grammar.rs", - "line": 482, + "line": 498, "decision": "!self.eat_contextual_kw(\"ROWID\")", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_490", + "id": "grammar_506", "file": "src/parser/grammar.rs", - "line": 490, + "line": 506, "decision": "matches!(&self.peek().kind, TokenKind::Identifier(id) if id.eq_ignore_ascii_case(\"STRICT\"))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_517", + "id": "grammar_533", "file": "src/parser/grammar.rs", - "line": 517, + "line": 533, "decision": "matches!(self.peek().kind, TokenKind::Identifier(_))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_535", + "id": "grammar_551", "file": "src/parser/grammar.rs", - "line": 535, + "line": 551, "decision": "named", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_538", + "id": "grammar_554", "file": "src/parser/grammar.rs", - "line": 538, + "line": 554, "decision": "self.eat_kw(Keyword::NOT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_543", + "id": "grammar_559", "file": "src/parser/grammar.rs", - "line": 543, + "line": 559, "decision": "matches!(self.peek().kind, TokenKind::Null)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_546", + "id": "grammar_562", "file": "src/parser/grammar.rs", - "line": 546, + "line": 562, "decision": "self.eat_kw(Keyword::PRIMARY)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_548", + "id": "grammar_564", "file": "src/parser/grammar.rs", - "line": 548, + "line": 564, "decision": "self.eat_kw(Keyword::ASC)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_550", + "id": "grammar_566", "file": "src/parser/grammar.rs", - "line": 550, + "line": 566, "decision": "self.eat_kw(Keyword::DESC)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_562", + "id": "grammar_578", "file": "src/parser/grammar.rs", - "line": 562, + "line": 578, "decision": "self.eat_kw(Keyword::UNIQUE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_566", + "id": "grammar_582", "file": "src/parser/grammar.rs", - "line": 566, + "line": 582, "decision": "self.eat_kw(Keyword::CHECK)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_572", + "id": "grammar_588", "file": "src/parser/grammar.rs", - "line": 572, + "line": 588, "decision": "self.eat_kw(Keyword::DEFAULT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_575", + "id": "grammar_591", "file": "src/parser/grammar.rs", - "line": 575, + "line": 591, "decision": "self.eat_kw(Keyword::COLLATE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_579", + "id": "grammar_595", "file": "src/parser/grammar.rs", - "line": 579, + "line": 595, "decision": "self.at_kw(Keyword::REFERENCES)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_583", + "id": "grammar_599", "file": "src/parser/grammar.rs", - "line": 583, + "line": 599, "decision": "self.at_kw(Keyword::GENERATED)\n || (self.at_kw(Keyword::AS) && matches!(self.peek_at(1).kind, TokenKind::LParen))", "conditions": 3, "vectors_required": 4, "compiler_void": false }, { - "id": "grammar_588", + "id": "grammar_604", "file": "src/parser/grammar.rs", - "line": 588, + "line": 604, "decision": "named", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_595", + "id": "grammar_611", "file": "src/parser/grammar.rs", - "line": 595, + "line": 611, "decision": "self.eat_punct(&TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_600", + "id": "grammar_616", "file": "src/parser/grammar.rs", - "line": 600, + "line": 616, "decision": "matches!(self.peek().kind, TokenKind::Plus | TokenKind::Minus)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_601", + "id": "grammar_617", "file": "src/parser/grammar.rs", - "line": 601, + "line": 617, "decision": "matches!(self.peek().kind, TokenKind::Minus)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_624", + "id": "grammar_640", "file": "src/parser/grammar.rs", - "line": 624, - "decision": "match tok.kind {\n TokenKind::Integer(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Integer(v)),\n span: tok.span,\n })\n }\n TokenKind::Float(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Float(v)),\n span: tok.span,\n })\n }\n TokenKind::String(s) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Str(s)),\n span: tok.span,\n })\n }\n TokenKind::Blob(b) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Blob(b)),\n span: tok.span,\n })\n }\n TokenKind::Null => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Null),\n span: tok.span,\n })\n }\n TokenKind::True => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::True),\n span: tok.span,\n })\n }\n TokenKind::False => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::False),\n span: tok.span,\n })\n }\n TokenKind::Keyword(Keyword::CURRENT_TIME)\n | TokenKind::Keyword(Keyword::CURRENT_DATE)\n | TokenKind::Keyword(Keyword::CURRENT_TIMESTAMP) => {\n self.unsupported(\"CURRENT_TIME/CURRENT_DATE/CURRENT_TIMESTAMP not yet supported\")\n }\n _ => self.invalid(\"expected literal value after DEFAULT\"),\n }", + "line": 640, + "decision": "match tok.kind {\n TokenKind::Integer(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Integer(v)),\n span: tok.span,\n })\n }\n TokenKind::Float(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Float(v)),\n span: tok.span,\n })\n }\n TokenKind::String(s) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Str(s)),\n span: tok.span,\n })\n }\n TokenKind::Blob(b) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Blob(*b)),\n span: tok.span,\n })\n }\n TokenKind::Null => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Null),\n span: tok.span,\n })\n }\n TokenKind::True => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::True),\n span: tok.span,\n })\n }\n TokenKind::False => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::False),\n span: tok.span,\n })\n }\n TokenKind::Keyword(Keyword::CURRENT_TIME)\n | TokenKind::Keyword(Keyword::CURRENT_DATE)\n | TokenKind::Keyword(Keyword::CURRENT_TIMESTAMP) => {\n self.unsupported(\"CURRENT_TIME/CURRENT_DATE/CURRENT_TIMESTAMP not yet supported\")\n }\n _ => self.invalid(\"expected literal value after DEFAULT\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_684", + "id": "grammar_700", "file": "src/parser/grammar.rs", - "line": 684, + "line": 700, "decision": "self.eat_kw(Keyword::CONSTRAINT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_687", + "id": "grammar_703", "file": "src/parser/grammar.rs", - "line": 687, + "line": 703, "decision": "self.eat_kw(Keyword::PRIMARY)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_693", + "id": "grammar_709", "file": "src/parser/grammar.rs", - "line": 693, + "line": 709, "decision": "self.eat_kw(Keyword::UNIQUE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_698", + "id": "grammar_714", "file": "src/parser/grammar.rs", - "line": 698, + "line": 714, "decision": "self.eat_kw(Keyword::CHECK)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_704", + "id": "grammar_720", "file": "src/parser/grammar.rs", - "line": 704, + "line": 720, "decision": "self.at_kw(Keyword::FOREIGN)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_713", + "id": "grammar_729", "file": "src/parser/grammar.rs", - "line": 713, + "line": 729, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_722", + "id": "grammar_738", "file": "src/parser/grammar.rs", - "line": 722, + "line": 738, "decision": "self.eat_kw(Keyword::ASC)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_724", + "id": "grammar_740", "file": "src/parser/grammar.rs", - "line": 724, + "line": 740, "decision": "self.eat_kw(Keyword::DESC)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_747", + "id": "grammar_763", "file": "src/parser/grammar.rs", - "line": 747, + "line": 763, "decision": "self.eat_kw(Keyword::WHERE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_769", + "id": "grammar_785", "file": "src/parser/grammar.rs", - "line": 769, + "line": 785, "decision": "self.at_kw(Keyword::TEMP) || self.at_kw(Keyword::TEMPORARY)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_777", + "id": "grammar_793", "file": "src/parser/grammar.rs", - "line": 777, + "line": 793, "decision": "self.eat_punct(&TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_779", + "id": "grammar_795", "file": "src/parser/grammar.rs", - "line": 779, + "line": 795, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_870", + "id": "grammar_886", "file": "src/parser/grammar.rs", - "line": 870, + "line": 886, "decision": "self.at_kw(Keyword::COMMIT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_895", + "id": "grammar_911", "file": "src/parser/grammar.rs", - "line": 895, + "line": 911, "decision": "self.at_kw(kw)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_914", + "id": "grammar_930", "file": "src/parser/grammar.rs", - "line": 914, + "line": 930, "decision": "name.eq_ignore_ascii_case(\"integrity_check\") || name.eq_ignore_ascii_case(\"quick_check\")", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_920", + "id": "grammar_936", "file": "src/parser/grammar.rs", - "line": 920, + "line": 936, "decision": "self.eat_punct(&TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_928", + "id": "grammar_944", "file": "src/parser/grammar.rs", - "line": 928, + "line": 944, "decision": "!name.eq_ignore_ascii_case(\"journal_mode\")", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_935", + "id": "grammar_951", "file": "src/parser/grammar.rs", - "line": 935, + "line": 951, "decision": "!self.eat_punct(&TokenKind::Eq)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_952", + "id": "grammar_968", "file": "src/parser/grammar.rs", - "line": 952, - "decision": "match self.peek().kind.clone() {\n TokenKind::Identifier(text) if text.eq_ignore_ascii_case(\"wal\") => {\n let span = self.advance().span;\n Ok((PragmaJournalMode::Wal, span))\n }\n TokenKind::Keyword(Keyword::DELETE) => {\n let span = self.advance().span;\n Ok((PragmaJournalMode::Delete, span))\n }\n _ => self.unsupported(\"unsupported journal_mode value (only WAL/DELETE are supported)\"),\n }", + "line": 968, + "decision": "match self.peek().kind.clone() {\n TokenKind::Identifier(text) if text.eq_ignore_ascii_case(\"wal\") => {\n let span = self.advance_span();\n Ok((PragmaJournalMode::Wal, span))\n }\n TokenKind::Keyword(Keyword::DELETE) => {\n let span = self.advance_span();\n Ok((PragmaJournalMode::Delete, span))\n }\n _ => self.unsupported(\"unsupported journal_mode value (only WAL/DELETE are supported)\"),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_953", + "id": "grammar_969", "file": "src/parser/grammar.rs", - "line": 953, + "line": 969, "decision": "text.eq_ignore_ascii_case(\"wal\")", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_977", + "id": "grammar_993", "file": "src/parser/grammar.rs", - "line": 977, + "line": 993, "decision": "matches!(self.peek().kind, TokenKind::Identifier(_))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_980", + "id": "grammar_996", "file": "src/parser/grammar.rs", - "line": 980, + "line": 996, "decision": "self.eat_punct(&TokenKind::Dot)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1002", + "id": "grammar_1018", "file": "src/parser/grammar.rs", - "line": 1002, + "line": 1018, "decision": "self.eat_kw(Keyword::QUERY)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1016", + "id": "grammar_1032", "file": "src/parser/grammar.rs", - "line": 1016, + "line": 1032, "decision": "self.at_kw(Keyword::WITH)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1021", + "id": "grammar_1037", "file": "src/parser/grammar.rs", - "line": 1021, + "line": 1037, "decision": "self.at_kw(Keyword::VALUES)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1030", + "id": "grammar_1046", "file": "src/parser/grammar.rs", - "line": 1030, + "line": 1046, "decision": "with_clause.is_some()\n && (self.at_kw(Keyword::INSERT)\n || self.at_kw(Keyword::UPDATE)\n || self.at_kw(Keyword::DELETE))", "conditions": 4, "vectors_required": 5, "compiler_void": false }, { - "id": "grammar_1040", + "id": "grammar_1056", "file": "src/parser/grammar.rs", - "line": 1040, + "line": 1056, "decision": "self.eat_kw(Keyword::DISTINCT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1042", + "id": "grammar_1058", "file": "src/parser/grammar.rs", - "line": 1042, + "line": 1058, "decision": "self.eat_kw(Keyword::ALL)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1049", + "id": "grammar_1065", "file": "src/parser/grammar.rs", - "line": 1049, + "line": 1065, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1053", + "id": "grammar_1069", "file": "src/parser/grammar.rs", - "line": 1053, + "line": 1069, "decision": "self.eat_kw(Keyword::FROM)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1059", + "id": "grammar_1075", "file": "src/parser/grammar.rs", - "line": 1059, + "line": 1075, "decision": "self.at_kw(Keyword::WINDOW)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1063", + "id": "grammar_1079", "file": "src/parser/grammar.rs", - "line": 1063, + "line": 1079, "decision": "self.eat_kw(Keyword::WHERE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1071", + "id": "grammar_1087", "file": "src/parser/grammar.rs", - "line": 1071, + "line": 1087, "decision": "self.eat_kw(Keyword::GROUP)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1074", + "id": "grammar_1090", "file": "src/parser/grammar.rs", - "line": 1074, + "line": 1090, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1077", + "id": "grammar_1093", "file": "src/parser/grammar.rs", - "line": 1077, + "line": 1093, "decision": "self.eat_kw(Keyword::HAVING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1080", + "id": "grammar_1096", "file": "src/parser/grammar.rs", - "line": 1080, + "line": 1096, "decision": "self.eat_kw(Keyword::HAVING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1089", + "id": "grammar_1105", "file": "src/parser/grammar.rs", - "line": 1089, + "line": 1105, "decision": "self.at_kw(Keyword::INTERSECT) || self.at_kw(Keyword::EXCEPT)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_1092", + "id": "grammar_1108", "file": "src/parser/grammar.rs", - "line": 1092, + "line": 1108, "decision": "!self.at_kw(Keyword::UNION)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1096", + "id": "grammar_1112", "file": "src/parser/grammar.rs", - "line": 1096, + "line": 1112, "decision": "self.eat_kw(Keyword::ALL)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1105", + "id": "grammar_1121", "file": "src/parser/grammar.rs", - "line": 1105, + "line": 1121, "decision": "self.eat_kw(Keyword::ORDER)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1108", + "id": "grammar_1124", "file": "src/parser/grammar.rs", - "line": 1108, + "line": 1124, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1113", + "id": "grammar_1129", "file": "src/parser/grammar.rs", - "line": 1113, + "line": 1129, "decision": "self.eat_kw(Keyword::LIMIT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1115", + "id": "grammar_1131", "file": "src/parser/grammar.rs", - "line": 1115, + "line": 1131, "decision": "self.eat_kw(Keyword::OFFSET) || self.eat_punct(&TokenKind::Comma)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_1152", + "id": "grammar_1168", "file": "src/parser/grammar.rs", - "line": 1152, + "line": 1168, "decision": "self.at_kw(Keyword::RECURSIVE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1156", + "id": "grammar_1172", "file": "src/parser/grammar.rs", - "line": 1156, + "line": 1172, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1170", + "id": "grammar_1186", "file": "src/parser/grammar.rs", - "line": 1170, + "line": 1186, "decision": "self.eat_punct(&TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1172", + "id": "grammar_1188", "file": "src/parser/grammar.rs", - "line": 1172, + "line": 1188, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1186", + "id": "grammar_1202", "file": "src/parser/grammar.rs", - "line": 1186, + "line": 1202, "decision": "self.at_kw(Keyword::MATERIALIZED)\n || (self.at_kw(Keyword::NOT)\n && matches!(\n self.peek_at(1).kind,\n TokenKind::Keyword(Keyword::MATERIALIZED)\n ))", "conditions": 3, "vectors_required": 4, "compiler_void": false }, { - "id": "grammar_1216", + "id": "grammar_1232", "file": "src/parser/grammar.rs", - "line": 1216, + "line": 1232, "decision": "self.at_kw(Keyword::VALUES)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1221", + "id": "grammar_1237", "file": "src/parser/grammar.rs", - "line": 1221, + "line": 1237, "decision": "self.eat_kw(Keyword::DISTINCT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1223", + "id": "grammar_1239", "file": "src/parser/grammar.rs", - "line": 1223, + "line": 1239, "decision": "self.eat_kw(Keyword::ALL)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1230", + "id": "grammar_1246", "file": "src/parser/grammar.rs", - "line": 1230, + "line": 1246, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1234", + "id": "grammar_1250", "file": "src/parser/grammar.rs", - "line": 1234, + "line": 1250, "decision": "self.eat_kw(Keyword::FROM)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1240", + "id": "grammar_1256", "file": "src/parser/grammar.rs", - "line": 1240, + "line": 1256, "decision": "self.at_kw(Keyword::WINDOW)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1244", + "id": "grammar_1260", "file": "src/parser/grammar.rs", - "line": 1244, + "line": 1260, "decision": "self.eat_kw(Keyword::WHERE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1252", + "id": "grammar_1268", "file": "src/parser/grammar.rs", - "line": 1252, + "line": 1268, "decision": "self.eat_kw(Keyword::GROUP)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1255", + "id": "grammar_1271", "file": "src/parser/grammar.rs", - "line": 1255, + "line": 1271, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1258", + "id": "grammar_1274", "file": "src/parser/grammar.rs", - "line": 1258, + "line": 1274, "decision": "self.eat_kw(Keyword::HAVING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1261", + "id": "grammar_1277", "file": "src/parser/grammar.rs", - "line": 1261, + "line": 1277, "decision": "self.at_kw(Keyword::HAVING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1282", + "id": "grammar_1298", "file": "src/parser/grammar.rs", - "line": 1282, + "line": 1298, "decision": "self.eat_punct(&TokenKind::Star)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1288", + "id": "grammar_1304", "file": "src/parser/grammar.rs", - "line": 1288, + "line": 1304, "decision": "matches!(self.peek_at(1).kind, TokenKind::Dot)\n && matches!(self.peek_at(2).kind, TokenKind::Star)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_1305", + "id": "grammar_1321", "file": "src/parser/grammar.rs", - "line": 1305, + "line": 1321, "decision": "self.eat_kw(Keyword::AS)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1313", + "id": "grammar_1329", "file": "src/parser/grammar.rs", - "line": 1313, + "line": 1329, "decision": "matches!(self.peek().kind, TokenKind::String(_))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1334", + "id": "grammar_1350", "file": "src/parser/grammar.rs", - "line": 1334, + "line": 1350, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1356", + "id": "grammar_1372", "file": "src/parser/grammar.rs", - "line": 1356, + "line": 1372, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1363", + "id": "grammar_1379", "file": "src/parser/grammar.rs", - "line": 1363, + "line": 1379, "decision": "self.eat_kw(Keyword::ON)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1365", + "id": "grammar_1381", "file": "src/parser/grammar.rs", - "line": 1365, + "line": 1381, "decision": "self.at_kw(Keyword::USING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1387", + "id": "grammar_1403", "file": "src/parser/grammar.rs", - "line": 1387, + "line": 1403, "decision": "self.at_kw(Keyword::OUTER)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1391", + "id": "grammar_1407", "file": "src/parser/grammar.rs", - "line": 1391, + "line": 1407, "decision": "self.eat_kw(Keyword::CROSS)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1393", + "id": "grammar_1409", "file": "src/parser/grammar.rs", - "line": 1393, + "line": 1409, "decision": "natural", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1397", + "id": "grammar_1413", "file": "src/parser/grammar.rs", - "line": 1397, + "line": 1413, "decision": "self.at_kw(Keyword::ON)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1400", + "id": "grammar_1416", "file": "src/parser/grammar.rs", - "line": 1400, + "line": 1416, "decision": "self.at_kw(Keyword::USING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1413", + "id": "grammar_1429", "file": "src/parser/grammar.rs", - "line": 1413, + "line": 1429, "decision": "self.eat_kw(Keyword::LEFT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1417", + "id": "grammar_1433", "file": "src/parser/grammar.rs", - "line": 1417, + "line": 1433, "decision": "self.eat_kw(Keyword::RIGHT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1421", + "id": "grammar_1437", "file": "src/parser/grammar.rs", - "line": 1421, + "line": 1437, "decision": "self.eat_kw(Keyword::FULL)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1425", + "id": "grammar_1441", "file": "src/parser/grammar.rs", - "line": 1425, + "line": 1441, "decision": "self.eat_kw(Keyword::INNER)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1428", + "id": "grammar_1444", "file": "src/parser/grammar.rs", - "line": 1428, + "line": 1444, "decision": "self.eat_kw(Keyword::JOIN)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1434", + "id": "grammar_1450", "file": "src/parser/grammar.rs", - "line": 1434, + "line": 1450, "decision": "natural", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1440", + "id": "grammar_1456", "file": "src/parser/grammar.rs", - "line": 1440, + "line": 1456, "decision": "natural", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1452", + "id": "grammar_1468", "file": "src/parser/grammar.rs", - "line": 1452, + "line": 1468, "decision": "self.at_kw(Keyword::USING)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1471", + "id": "grammar_1487", "file": "src/parser/grammar.rs", - "line": 1471, + "line": 1487, "decision": "!self.at_kw(Keyword::ON)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1495", + "id": "grammar_1511", "file": "src/parser/grammar.rs", - "line": 1495, + "line": 1511, "decision": "matches!(self.peek().kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1498", + "id": "grammar_1514", "file": "src/parser/grammar.rs", - "line": 1498, + "line": 1514, "decision": "!self.at_kw(Keyword::SELECT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1520", + "id": "grammar_1536", "file": "src/parser/grammar.rs", - "line": 1520, + "line": 1536, "decision": "matches!(self.peek().kind, TokenKind::Dot)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1525", + "id": "grammar_1541", "file": "src/parser/grammar.rs", - "line": 1525, + "line": 1541, "decision": "end", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1536", + "id": "grammar_1552", "file": "src/parser/grammar.rs", - "line": 1536, + "line": 1552, "decision": "self.at_kw(Keyword::INDEXED)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1539", + "id": "grammar_1555", "file": "src/parser/grammar.rs", - "line": 1539, + "line": 1555, "decision": "self.at_kw(Keyword::NOT)\n && matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::INDEXED))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_1544", + "id": "grammar_1560", "file": "src/parser/grammar.rs", - "line": 1544, + "line": 1560, "decision": "matches!(self.peek().kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1557", + "id": "grammar_1573", "file": "src/parser/grammar.rs", - "line": 1557, + "line": 1573, "decision": "self.eat_kw(Keyword::ASC)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1559", + "id": "grammar_1575", "file": "src/parser/grammar.rs", - "line": 1559, + "line": 1575, "decision": "self.eat_kw(Keyword::DESC)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1564", + "id": "grammar_1580", "file": "src/parser/grammar.rs", - "line": 1564, + "line": 1580, "decision": "self.eat_kw(Keyword::NULLS)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1565", + "id": "grammar_1581", "file": "src/parser/grammar.rs", - "line": 1565, + "line": 1581, "decision": "self.eat_kw(Keyword::FIRST)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1567", + "id": "grammar_1583", "file": "src/parser/grammar.rs", - "line": 1567, + "line": 1583, "decision": "self.eat_kw(Keyword::LAST)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1601", + "id": "grammar_1617", "file": "src/parser/grammar.rs", - "line": 1601, + "line": 1617, "decision": "self.at_kw(Keyword::AND)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1602", + "id": "grammar_1618", "file": "src/parser/grammar.rs", - "line": 1602, + "line": 1618, "decision": "min_prec > 1", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1607", + "id": "grammar_1623", "file": "src/parser/grammar.rs", - "line": 1607, + "line": 1623, "decision": "self.at_kw(Keyword::OR)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1608", + "id": "grammar_1624", "file": "src/parser/grammar.rs", - "line": 1608, + "line": 1624, "decision": "min_prec > 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1622", + "id": "grammar_1638", "file": "src/parser/grammar.rs", - "line": 1622, + "line": 1638, "decision": "this.at_kw(Keyword::NOT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1624", + "id": "grammar_1640", "file": "src/parser/grammar.rs", - "line": 1624, + "line": 1640, "decision": "this.at_kw(Keyword::EXISTS)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1648", + "id": "grammar_1664", "file": "src/parser/grammar.rs", - "line": 1648, - "decision": "match self.peek().kind.clone() {\n TokenKind::Eq => {\n self.advance();\n let rhs = self.binary_expr(1)?;\n bin(BinaryOp::Eq, lhs, rhs)\n }\n TokenKind::Ne => {\n self.advance();\n let rhs = self.binary_expr(1)?;\n bin(BinaryOp::Ne, lhs, rhs)\n }\n TokenKind::Keyword(Keyword::IS) => {\n self.advance();\n let negated = self.eat_kw(Keyword::NOT);\n let rhs = self.binary_expr(1)?;\n let span = join_span(lhs.span, rhs.span);\n Expr {\n kind: ExprKind::Is {\n lhs: Box::new(lhs),\n rhs: Box::new(rhs),\n negated,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::ISNULL) => {\n let end = self.advance().span;\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: false,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::NOTNULL) => {\n let end = self.advance().span;\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::BETWEEN) => {\n self.advance();\n let (lo, hi) = self.between_tail()?;\n let span = join_span(lhs.span, hi.span);\n Expr {\n kind: ExprKind::Between {\n expr: Box::new(lhs),\n lo: Box::new(lo),\n hi: Box::new(hi),\n negated: false,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::IN) => {\n self.advance();\n self.in_tail(lhs, false)?\n }\n TokenKind::Keyword(Keyword::LIKE) | TokenKind::Keyword(Keyword::GLOB) => {\n let glob = self.at_kw(Keyword::GLOB);\n self.advance();\n self.like_tail(lhs, glob, false)?\n }\n TokenKind::Keyword(Keyword::NOT) => match self.peek_at(1).kind.clone() {\n TokenKind::Null => {\n self.advance();\n let end = self.advance().span;\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::BETWEEN) => {\n self.advance();\n self.advance();\n let (lo, hi) = self.between_tail()?;\n let span = join_span(lhs.span, hi.span);\n Expr {\n kind: ExprKind::Between {\n expr: Box::new(lhs),\n lo: Box::new(lo),\n hi: Box::new(hi),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::IN) => {\n self.advance();\n self.advance();\n self.in_tail(lhs, true)?\n }\n TokenKind::Keyword(Keyword::LIKE) | TokenKind::Keyword(Keyword::GLOB) => {\n let glob =\n matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::GLOB));\n self.advance();\n self.advance();\n self.like_tail(lhs, glob, true)?\n }\n _ => break,\n },\n _ => break,\n }", + "line": 1664, + "decision": "match self.peek().kind.clone() {\n TokenKind::Eq => {\n self.advance();\n let rhs = self.binary_expr(1)?;\n bin(BinaryOp::Eq, lhs, rhs)\n }\n TokenKind::Ne => {\n self.advance();\n let rhs = self.binary_expr(1)?;\n bin(BinaryOp::Ne, lhs, rhs)\n }\n TokenKind::Keyword(Keyword::IS) => {\n self.advance();\n let negated = self.eat_kw(Keyword::NOT);\n let rhs = self.binary_expr(1)?;\n let span = join_span(lhs.span, rhs.span);\n Expr {\n kind: ExprKind::Is {\n lhs: Box::new(lhs),\n rhs: Box::new(rhs),\n negated,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::ISNULL) => {\n let end = self.advance_span();\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: false,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::NOTNULL) => {\n let end = self.advance_span();\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::BETWEEN) => {\n self.advance();\n let (lo, hi) = self.between_tail()?;\n let span = join_span(lhs.span, hi.span);\n Expr {\n kind: ExprKind::Between {\n expr: Box::new(lhs),\n lo: Box::new(lo),\n hi: Box::new(hi),\n negated: false,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::IN) => {\n self.advance();\n self.in_tail(lhs, false)?\n }\n TokenKind::Keyword(Keyword::LIKE) | TokenKind::Keyword(Keyword::GLOB) => {\n let glob = self.at_kw(Keyword::GLOB);\n self.advance();\n self.like_tail(lhs, glob, false)?\n }\n TokenKind::Keyword(Keyword::NOT) => match self.peek_at(1).kind.clone() {\n TokenKind::Null => {\n self.advance();\n let end = self.advance_span();\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::BETWEEN) => {\n self.advance();\n self.advance();\n let (lo, hi) = self.between_tail()?;\n let span = join_span(lhs.span, hi.span);\n Expr {\n kind: ExprKind::Between {\n expr: Box::new(lhs),\n lo: Box::new(lo),\n hi: Box::new(hi),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::IN) => {\n self.advance();\n self.advance();\n self.in_tail(lhs, true)?\n }\n TokenKind::Keyword(Keyword::LIKE) | TokenKind::Keyword(Keyword::GLOB) => {\n let glob =\n matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::GLOB));\n self.advance();\n self.advance();\n self.like_tail(lhs, glob, true)?\n }\n _ => break,\n },\n _ => break,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_1718", + "id": "grammar_1734", "file": "src/parser/grammar.rs", - "line": 1718, - "decision": "match self.peek_at(1).kind.clone() {\n TokenKind::Null => {\n self.advance();\n let end = self.advance().span;\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::BETWEEN) => {\n self.advance();\n self.advance();\n let (lo, hi) = self.between_tail()?;\n let span = join_span(lhs.span, hi.span);\n Expr {\n kind: ExprKind::Between {\n expr: Box::new(lhs),\n lo: Box::new(lo),\n hi: Box::new(hi),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::IN) => {\n self.advance();\n self.advance();\n self.in_tail(lhs, true)?\n }\n TokenKind::Keyword(Keyword::LIKE) | TokenKind::Keyword(Keyword::GLOB) => {\n let glob =\n matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::GLOB));\n self.advance();\n self.advance();\n self.like_tail(lhs, glob, true)?\n }\n _ => break,\n }", + "line": 1734, + "decision": "match self.peek_at(1).kind.clone() {\n TokenKind::Null => {\n self.advance();\n let end = self.advance_span();\n let span = join_span(lhs.span, end);\n Expr {\n kind: ExprKind::IsNull {\n expr: Box::new(lhs),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::BETWEEN) => {\n self.advance();\n self.advance();\n let (lo, hi) = self.between_tail()?;\n let span = join_span(lhs.span, hi.span);\n Expr {\n kind: ExprKind::Between {\n expr: Box::new(lhs),\n lo: Box::new(lo),\n hi: Box::new(hi),\n negated: true,\n },\n span,\n }\n }\n TokenKind::Keyword(Keyword::IN) => {\n self.advance();\n self.advance();\n self.in_tail(lhs, true)?\n }\n TokenKind::Keyword(Keyword::LIKE) | TokenKind::Keyword(Keyword::GLOB) => {\n let glob =\n matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::GLOB));\n self.advance();\n self.advance();\n self.like_tail(lhs, glob, true)?\n }\n _ => break,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_1780", + "id": "grammar_1796", "file": "src/parser/grammar.rs", - "line": 1780, + "line": 1796, "decision": "!self.at_kw(Keyword::SELECT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1784", + "id": "grammar_1800", "file": "src/parser/grammar.rs", - "line": 1784, + "line": 1800, "decision": "matches!(\n self.peek().kind,\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT)\n )", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1819", + "id": "grammar_1835", "file": "src/parser/grammar.rs", - "line": 1819, + "line": 1835, "decision": "match self.tokens.get(idx) {\n Some(t) => &t.kind,\n None => return false,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_1823", + "id": "grammar_1839", "file": "src/parser/grammar.rs", - "line": 1823, + "line": 1839, "decision": "match kind {\n TokenKind::Eof => return false,\n TokenKind::LParen => depth = depth.saturating_add(1),\n TokenKind::RParen => {\n if depth == 0 {\n let after_in = matches!(\n self.tokens.get(idx.saturating_add(1)).map(|t| &t.kind),\n Some(TokenKind::Keyword(Keyword::IN))\n );\n let after_not_in = matches!(\n self.tokens.get(idx.saturating_add(1)).map(|t| &t.kind),\n Some(TokenKind::Keyword(Keyword::NOT))\n ) && matches!(\n self.tokens.get(idx.saturating_add(2)).map(|t| &t.kind),\n Some(TokenKind::Keyword(Keyword::IN))\n );\n return saw_top_comma && (after_in || after_not_in);\n }\n depth = depth.saturating_sub(1);\n }\n TokenKind::Comma if depth == 0 => saw_top_comma = true,\n _ => {}\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_1843", + "id": "grammar_1859", "file": "src/parser/grammar.rs", - "line": 1843, + "line": 1859, "decision": "depth == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1827", + "id": "grammar_1843", "file": "src/parser/grammar.rs", - "line": 1827, + "line": 1843, "decision": "depth == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1862", + "id": "grammar_1878", "file": "src/parser/grammar.rs", - "line": 1862, + "line": 1878, "decision": "!matches!(self.peek().kind, TokenKind::LParen) || !self.looks_like_tuple_in()", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_1868", + "id": "grammar_1884", "file": "src/parser/grammar.rs", - "line": 1868, + "line": 1884, "decision": "match self.expr_list() {\n Ok(list) => list,\n Err(_) => {\n self.pos = start_pos;\n return Ok(None);\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_1875", + "id": "grammar_1891", "file": "src/parser/grammar.rs", - "line": 1875, + "line": 1891, "decision": "self.expect_punct(TokenKind::RParen, \"')'\").is_err()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1879", + "id": "grammar_1895", "file": "src/parser/grammar.rs", - "line": 1879, + "line": 1895, "decision": "self.at_kw(Keyword::IN)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1882", + "id": "grammar_1898", "file": "src/parser/grammar.rs", - "line": 1882, + "line": 1898, "decision": "self.at_kw(Keyword::NOT)\n && matches!(self.peek_at(1).kind, TokenKind::Keyword(Keyword::IN))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_1892", + "id": "grammar_1908", "file": "src/parser/grammar.rs", - "line": 1892, + "line": 1908, "decision": "list.len() < 2", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1897", + "id": "grammar_1913", "file": "src/parser/grammar.rs", - "line": 1897, + "line": 1913, "decision": "!self.at_kw(Keyword::SELECT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1902", + "id": "grammar_1918", "file": "src/parser/grammar.rs", - "line": 1902, + "line": 1918, "decision": "matches!(\n self.peek().kind,\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT)\n )", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1923", + "id": "grammar_1939", "file": "src/parser/grammar.rs", - "line": 1923, + "line": 1939, "decision": "!matches!(self.peek().kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1927", + "id": "grammar_1943", "file": "src/parser/grammar.rs", - "line": 1927, + "line": 1943, "decision": "self.at_kw(Keyword::SELECT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1929", + "id": "grammar_1945", "file": "src/parser/grammar.rs", - "line": 1929, + "line": 1945, "decision": "matches!(\n self.peek().kind,\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT)\n )", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1949", + "id": "grammar_1965", "file": "src/parser/grammar.rs", - "line": 1949, + "line": 1965, "decision": "matches!(self.peek().kind, TokenKind::RParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_1969", + "id": "grammar_1985", "file": "src/parser/grammar.rs", - "line": 1969, + "line": 1985, "decision": "self.eat_kw(Keyword::ESCAPE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2005", + "id": "grammar_2021", "file": "src/parser/grammar.rs", - "line": 2005, + "line": 2021, "decision": "prec < min_prec", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2016", + "id": "grammar_2032", "file": "src/parser/grammar.rs", - "line": 2016, + "line": 2032, "decision": "match kind {\n TokenKind::Lt => (BinaryOp::Lt, 1),\n TokenKind::Le => (BinaryOp::Le, 1),\n TokenKind::Gt => (BinaryOp::Gt, 1),\n TokenKind::Ge => (BinaryOp::Ge, 1),\n TokenKind::BitAnd => (BinaryOp::BitAnd, 2),\n TokenKind::BitOr => (BinaryOp::BitOr, 2),\n TokenKind::Shl => (BinaryOp::Shl, 2),\n TokenKind::Shr => (BinaryOp::Shr, 2),\n TokenKind::Plus => (BinaryOp::Add, 3),\n TokenKind::Minus => (BinaryOp::Sub, 3),\n TokenKind::Star => (BinaryOp::Mul, 4),\n TokenKind::Slash => (BinaryOp::Div, 4),\n TokenKind::Percent => (BinaryOp::Mod, 4),\n TokenKind::Concat => (BinaryOp::Concat, 5),\n _ => return None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_2040", + "id": "grammar_2056", "file": "src/parser/grammar.rs", - "line": 2040, + "line": 2056, "decision": "matches!(self.peek().kind, TokenKind::Arrow | TokenKind::ArrowArrow)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2048", + "id": "grammar_2064", "file": "src/parser/grammar.rs", - "line": 2048, + "line": 2064, "decision": "self.eat_kw(Keyword::COLLATE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2064", + "id": "grammar_2080", "file": "src/parser/grammar.rs", - "line": 2064, + "line": 2080, "decision": "match this.peek().kind {\n TokenKind::Plus => Some(UnaryOp::Plus),\n TokenKind::Minus => Some(UnaryOp::Minus),\n TokenKind::BitNot => Some(UnaryOp::BitNot),\n _ => None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_2079", + "id": "grammar_2095", "file": "src/parser/grammar.rs", - "line": 2079, + "line": 2095, "decision": "matches!(op, UnaryOp::Minus)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2081", + "id": "grammar_2097", "file": "src/parser/grammar.rs", - "line": 2081, + "line": 2097, "decision": "f == 9_223_372_036_854_775_808.0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2103", + "id": "grammar_2119", "file": "src/parser/grammar.rs", - "line": 2103, - "decision": "match tok.kind {\n TokenKind::Integer(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Integer(v)),\n span: tok.span,\n })\n }\n TokenKind::Float(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Float(v)),\n span: tok.span,\n })\n }\n TokenKind::String(s) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Str(s)),\n span: tok.span,\n })\n }\n TokenKind::Blob(b) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Blob(b)),\n span: tok.span,\n })\n }\n TokenKind::Null => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Null),\n span: tok.span,\n })\n }\n TokenKind::True => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::True),\n span: tok.span,\n })\n }\n TokenKind::False => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::False),\n span: tok.span,\n })\n }\n TokenKind::Param(p) => {\n self.advance();\n let kind = match p {\n Param::Anonymous => ParamKind::Anonymous,\n Param::Numbered(n) => ParamKind::Numbered(n),\n Param::Colon(s) => ParamKind::Colon(s),\n Param::At(s) => ParamKind::At(s),\n Param::Dollar(s) => ParamKind::Dollar(s),\n };\n Ok(Expr {\n kind: ExprKind::Param(kind),\n span: tok.span,\n })\n }\n TokenKind::Keyword(Keyword::CURRENT_TIME)\n | TokenKind::Keyword(Keyword::CURRENT_DATE)\n | TokenKind::Keyword(Keyword::CURRENT_TIMESTAMP) => {\n self.unsupported(\"CURRENT_TIME/CURRENT_DATE/CURRENT_TIMESTAMP not yet supported\")\n }\n TokenKind::Keyword(Keyword::CASE) => self.case_expr(),\n TokenKind::Keyword(Keyword::CAST) => self.cast_expr(),\n TokenKind::Keyword(Keyword::EXISTS) => {\n let start = tok.span;\n self.advance();\n self.exists_tail(start, false)\n }\n TokenKind::Identifier(name) => {\n self.advance();\n if matches!(self.peek().kind, TokenKind::LParen) {\n return self.function_call(name, tok.span);\n }\n let mut parts = vec![name];\n while matches!(self.peek().kind, TokenKind::Dot) && parts.len() < 3 {\n self.advance();\n let (part, _) = self.identifier()?;\n parts.push(part);\n }\n let end = self\n .tokens\n .get(self.pos.saturating_sub(1))\n .map_or(tok.span, |t| t.span);\n let span = join_span(tok.span, end);\n let mut parts = parts.into_iter();\n let kind = match parts.len() {\n 1 => ExprKind::Column {\n table: None,\n catalog: None,\n name: parts.next().unwrap_or_default(),\n },\n 2 => ExprKind::Column {\n catalog: None,\n table: Some(parts.next().unwrap_or_default()),\n name: parts.next().unwrap_or_default(),\n },\n _ => ExprKind::Column {\n catalog: Some(parts.next().unwrap_or_default()),\n table: Some(parts.next().unwrap_or_default()),\n name: parts.next().unwrap_or_default(),\n },\n };\n Ok(Expr { kind, span })\n }\n // SQLite treats most keywords as usable function names when\n // followed by `(` (e.g. `replace(...)`, `glob(...)`) — only\n // the handful matched above (CASE/CAST/EXISTS/CURRENT_*)\n // are true reserved words in expression position.\n TokenKind::Keyword(kw) if matches!(self.peek_at(1).kind, TokenKind::LParen) => {\n self.advance();\n self.function_call(format!(\"{kw:?}\"), tok.span)\n }\n TokenKind::LParen => {\n self.advance();\n if self.at_kw(Keyword::SELECT) {\n let subquery = self.parse_select_stmt()?;\n if matches!(\n self.peek().kind,\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT)\n ) {\n return self.unsupported(\n \"compound SELECT (UNION/INTERSECT/EXCEPT) not yet supported\",\n );\n }\n let end = self.expect_punct(TokenKind::RParen, \"')' to close subquery\")?;\n let span = join_span(tok.span, end);\n return Ok(Expr {\n kind: ExprKind::Subquery(Box::new(subquery)),\n span,\n });\n }\n let inner = self.expr()?;\n let end = self.expect_punct(TokenKind::RParen, \"')' to close expression\")?;\n let span = join_span(tok.span, end);\n Ok(Expr {\n kind: ExprKind::Paren(Box::new(inner)),\n span,\n })\n }\n other => Err(ParseFail::Invalid {\n message: format!(\"expected column or expression, found {other:?}\"),\n span: tok.span,\n }),\n }", + "line": 2119, + "decision": "match tok.kind {\n TokenKind::Integer(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Integer(v)),\n span: tok.span,\n })\n }\n TokenKind::Float(v) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Float(v)),\n span: tok.span,\n })\n }\n TokenKind::String(s) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Str(s)),\n span: tok.span,\n })\n }\n TokenKind::Blob(b) => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Blob(*b)),\n span: tok.span,\n })\n }\n TokenKind::Null => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::Null),\n span: tok.span,\n })\n }\n TokenKind::True => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::True),\n span: tok.span,\n })\n }\n TokenKind::False => {\n self.advance();\n Ok(Expr {\n kind: ExprKind::Literal(Literal::False),\n span: tok.span,\n })\n }\n TokenKind::Param(p) => {\n self.advance();\n let kind = match *p {\n Param::Anonymous => ParamKind::Anonymous,\n Param::Numbered(n) => ParamKind::Numbered(n),\n Param::Colon(s) => ParamKind::Colon(s),\n Param::At(s) => ParamKind::At(s),\n Param::Dollar(s) => ParamKind::Dollar(s),\n };\n Ok(Expr {\n kind: ExprKind::Param(kind),\n span: tok.span,\n })\n }\n TokenKind::Keyword(Keyword::CURRENT_TIME)\n | TokenKind::Keyword(Keyword::CURRENT_DATE)\n | TokenKind::Keyword(Keyword::CURRENT_TIMESTAMP) => {\n self.unsupported(\"CURRENT_TIME/CURRENT_DATE/CURRENT_TIMESTAMP not yet supported\")\n }\n TokenKind::Keyword(Keyword::CASE) => self.case_expr(),\n TokenKind::Keyword(Keyword::CAST) => self.cast_expr(),\n TokenKind::Keyword(Keyword::EXISTS) => {\n let start = tok.span;\n self.advance();\n self.exists_tail(start, false)\n }\n TokenKind::Identifier(name) => {\n self.advance();\n if matches!(self.peek().kind, TokenKind::LParen) {\n return self.function_call(name, tok.span);\n }\n let mut parts = vec![name];\n while matches!(self.peek().kind, TokenKind::Dot) && parts.len() < 3 {\n self.advance();\n let (part, _) = self.identifier()?;\n parts.push(part);\n }\n let end = self\n .tokens\n .get(self.pos.saturating_sub(1))\n .map_or(tok.span, |t| t.span);\n let span = join_span(tok.span, end);\n let mut parts = parts.into_iter();\n let kind = match parts.len() {\n 1 => ExprKind::Column {\n table: None,\n catalog: None,\n name: parts.next().unwrap_or_default(),\n },\n 2 => ExprKind::Column {\n catalog: None,\n table: Some(parts.next().unwrap_or_default()),\n name: parts.next().unwrap_or_default(),\n },\n _ => ExprKind::Column {\n catalog: Some(parts.next().unwrap_or_default()),\n table: Some(parts.next().unwrap_or_default()),\n name: parts.next().unwrap_or_default(),\n },\n };\n Ok(Expr { kind, span })\n }\n // SQLite treats most keywords as usable function names when\n // followed by `(` (e.g. `replace(...)`, `glob(...)`) — only\n // the handful matched above (CASE/CAST/EXISTS/CURRENT_*)\n // are true reserved words in expression position.\n TokenKind::Keyword(kw) if matches!(self.peek_at(1).kind, TokenKind::LParen) => {\n self.advance();\n self.function_call(format!(\"{kw:?}\"), tok.span)\n }\n TokenKind::LParen => {\n self.advance();\n if self.at_kw(Keyword::SELECT) {\n let subquery = self.parse_select_stmt()?;\n if matches!(\n self.peek().kind,\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT)\n ) {\n return self.unsupported(\n \"compound SELECT (UNION/INTERSECT/EXCEPT) not yet supported\",\n );\n }\n let end = self.expect_punct(TokenKind::RParen, \"')' to close subquery\")?;\n let span = join_span(tok.span, end);\n return Ok(Expr {\n kind: ExprKind::Subquery(Box::new(subquery)),\n span,\n });\n }\n let inner = self.expr()?;\n let end = self.expect_punct(TokenKind::RParen, \"')' to close expression\")?;\n let span = join_span(tok.span, end);\n Ok(Expr {\n kind: ExprKind::Paren(Box::new(inner)),\n span,\n })\n }\n other => Err(ParseFail::Invalid {\n message: format!(\"expected column or expression, found {other:?}\"),\n span: tok.span,\n }),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_2219", + "id": "grammar_2235", "file": "src/parser/grammar.rs", - "line": 2219, + "line": 2235, "decision": "matches!(self.peek_at(1).kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2155", + "id": "grammar_2171", "file": "src/parser/grammar.rs", - "line": 2155, - "decision": "match p {\n Param::Anonymous => ParamKind::Anonymous,\n Param::Numbered(n) => ParamKind::Numbered(n),\n Param::Colon(s) => ParamKind::Colon(s),\n Param::At(s) => ParamKind::At(s),\n Param::Dollar(s) => ParamKind::Dollar(s),\n }", + "line": 2171, + "decision": "match *p {\n Param::Anonymous => ParamKind::Anonymous,\n Param::Numbered(n) => ParamKind::Numbered(n),\n Param::Colon(s) => ParamKind::Colon(s),\n Param::At(s) => ParamKind::At(s),\n Param::Dollar(s) => ParamKind::Dollar(s),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_2181", + "id": "grammar_2197", "file": "src/parser/grammar.rs", - "line": 2181, + "line": 2197, "decision": "matches!(self.peek().kind, TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2185", + "id": "grammar_2201", "file": "src/parser/grammar.rs", - "line": 2185, + "line": 2201, "decision": "matches!(self.peek().kind, TokenKind::Dot) && parts.len() < 3", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_2196", + "id": "grammar_2212", "file": "src/parser/grammar.rs", - "line": 2196, + "line": 2212, "decision": "match parts.len() {\n 1 => ExprKind::Column {\n table: None,\n catalog: None,\n name: parts.next().unwrap_or_default(),\n },\n 2 => ExprKind::Column {\n catalog: None,\n table: Some(parts.next().unwrap_or_default()),\n name: parts.next().unwrap_or_default(),\n },\n _ => ExprKind::Column {\n catalog: Some(parts.next().unwrap_or_default()),\n table: Some(parts.next().unwrap_or_default()),\n name: parts.next().unwrap_or_default(),\n },\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_2225", + "id": "grammar_2241", "file": "src/parser/grammar.rs", - "line": 2225, + "line": 2241, "decision": "self.at_kw(Keyword::SELECT)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2227", + "id": "grammar_2243", "file": "src/parser/grammar.rs", - "line": 2227, + "line": 2243, "decision": "matches!(\n self.peek().kind,\n TokenKind::Keyword(Keyword::UNION)\n | TokenKind::Keyword(Keyword::INTERSECT)\n | TokenKind::Keyword(Keyword::EXCEPT)\n )", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2262", + "id": "grammar_2278", "file": "src/parser/grammar.rs", - "line": 2262, + "line": 2278, "decision": "self.eat_punct(&TokenKind::Star)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2264", + "id": "grammar_2280", "file": "src/parser/grammar.rs", - "line": 2264, + "line": 2280, "decision": "matches!(self.peek().kind, TokenKind::RParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2270", + "id": "grammar_2286", "file": "src/parser/grammar.rs", - "line": 2270, + "line": 2286, "decision": "self.at_kw(Keyword::OVER) || self.at_kw(Keyword::FILTER)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "grammar_2289", + "id": "grammar_2305", "file": "src/parser/grammar.rs", - "line": 2289, + "line": 2305, "decision": "self.at_kw(Keyword::WHEN)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2295", + "id": "grammar_2311", "file": "src/parser/grammar.rs", - "line": 2295, + "line": 2311, "decision": "self.eat_kw(Keyword::WHEN)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2301", + "id": "grammar_2317", "file": "src/parser/grammar.rs", - "line": 2301, + "line": 2317, "decision": "whens.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2304", + "id": "grammar_2320", "file": "src/parser/grammar.rs", - "line": 2304, + "line": 2320, "decision": "self.eat_kw(Keyword::ELSE)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2345", + "id": "grammar_2361", "file": "src/parser/grammar.rs", - "line": 2345, + "line": 2361, "decision": "self.eat_punct(&TokenKind::LParen)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2349", + "id": "grammar_2365", "file": "src/parser/grammar.rs", - "line": 2349, + "line": 2365, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "grammar_2361", + "id": "grammar_2377", "file": "src/parser/grammar.rs", - "line": 2361, + "line": 2377, "decision": "match self.peek().kind.clone() {\n TokenKind::Integer(v) => {\n self.advance();\n Ok(v.to_string())\n }\n other => {\n let span = self.peek().span;\n Err(ParseFail::Invalid {\n message: format!(\"expected number, found {other:?}\"),\n span,\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "grammar_2378", + "id": "grammar_2394", "file": "src/parser/grammar.rs", - "line": 2378, + "line": 2394, "decision": "self.eat_punct(&TokenKind::Comma)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_587", + "id": "tokenizer_606", "file": "src/parser/tokenizer.rs", - "line": 587, - "decision": "match upper.as_str() {\n \"NULL\" => return TokenKind::Null,\n \"TRUE\" => return TokenKind::True,\n \"FALSE\" => return TokenKind::False,\n _ => {}\n }", - "conditions": 0, - "vectors_required": 0, - "compiler_void": true + "line": 606, + "decision": "word.eq_ignore_ascii_case(\"NULL\")", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false }, { - "id": "tokenizer_593", + "id": "tokenizer_609", "file": "src/parser/tokenizer.rs", - "line": 593, - "decision": "match KEYWORDS.binary_search_by(|(text, _)| (*text).cmp(upper.as_str())) {\n // `Ok(idx)` proves `idx` is in bounds, so `.get` never hits the\n // `unwrap_or_else` fallback; it's written this way (rather than\n // indexing) because the qualified subset denies\n // `clippy::indexing_slicing`/`unwrap_used`/`expect_used`.\n Ok(idx) => KEYWORDS\n .get(idx)\n .map(|(_, kw)| TokenKind::Keyword(*kw))\n .unwrap_or_else(|| TokenKind::Identifier(word.to_string())),\n Err(_) => TokenKind::Identifier(word.to_string()),\n }", + "line": 609, + "decision": "word.eq_ignore_ascii_case(\"TRUE\")", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "tokenizer_612", + "file": "src/parser/tokenizer.rs", + "line": 612, + "decision": "word.eq_ignore_ascii_case(\"FALSE\")", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "tokenizer_615", + "file": "src/parser/tokenizer.rs", + "line": 615, + "decision": "match KEYWORDS.binary_search_by(|(text, _)| cmp_ignore_ascii_case(text, word)) {\n // `Ok(idx)` proves `idx` is in bounds, so `.get` never hits the\n // `unwrap_or_else` fallback; it's written this way (rather than\n // indexing) because the qualified subset denies\n // `clippy::indexing_slicing`/`unwrap_used`/`expect_used`.\n Ok(idx) => KEYWORDS\n .get(idx)\n .map(|(_, kw)| TokenKind::Keyword(*kw))\n .unwrap_or_else(|| TokenKind::Identifier(word.to_string())),\n Err(_) => TokenKind::Identifier(word.to_string()),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_638", + "id": "tokenizer_670", "file": "src/parser/tokenizer.rs", - "line": 638, + "line": 670, "decision": "is_eof", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_664", + "id": "tokenizer_698", "file": "src/parser/tokenizer.rs", - "line": 664, + "line": 698, "decision": "c == '\\n'", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_692", + "id": "tokenizer_725", "file": "src/parser/tokenizer.rs", - "line": 692, + "line": 725, "decision": "match self.peek_char() {\n Some(c) if c.is_whitespace() => {\n self.bump();\n }\n Some('-') => {\n // Lookahead for `--` line comment without consuming\n // a lone `-` (the Minus operator).\n if self.peek_at(1) == Some('-') {\n self.bump();\n self.bump();\n while let Some(c) = self.peek_char() {\n if c == '\\n' {\n break;\n }\n self.bump();\n }\n continue;\n }\n break;\n }\n Some('/') => {\n if self.peek_at(1) == Some('*') {\n self.bump();\n self.bump();\n loop {\n match self.peek_char() {\n None => {\n return Some(\"unterminated block comment\".to_string());\n }\n Some('*') => {\n self.bump();\n if self.peek_char() == Some('/') {\n self.bump();\n break;\n }\n }\n Some(_) => {\n self.bump();\n }\n }\n }\n continue;\n }\n break;\n }\n _ => break,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_693", + "id": "tokenizer_726", "file": "src/parser/tokenizer.rs", - "line": 693, + "line": 726, "decision": "c.is_whitespace()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_699", + "id": "tokenizer_732", "file": "src/parser/tokenizer.rs", - "line": 699, + "line": 732, "decision": "self.peek_at(1) == Some('-')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_703", + "id": "tokenizer_736", "file": "src/parser/tokenizer.rs", - "line": 703, + "line": 736, "decision": "c == '\\n'", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_713", + "id": "tokenizer_746", "file": "src/parser/tokenizer.rs", - "line": 713, + "line": 746, "decision": "self.peek_at(1) == Some('*')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_717", + "id": "tokenizer_750", "file": "src/parser/tokenizer.rs", - "line": 717, + "line": 750, "decision": "match self.peek_char() {\n None => {\n return Some(\"unterminated block comment\".to_string());\n }\n Some('*') => {\n self.bump();\n if self.peek_char() == Some('/') {\n self.bump();\n break;\n }\n }\n Some(_) => {\n self.bump();\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_723", + "id": "tokenizer_756", "file": "src/parser/tokenizer.rs", - "line": 723, + "line": 756, "decision": "self.peek_char() == Some('/')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_764", + "id": "tokenizer_797", "file": "src/parser/tokenizer.rs", - "line": 764, + "line": 797, "decision": "match c {\n '0'..='9' => self.scan_number(),\n '.' => {\n // Lookahead: `.5` is a float; a lone `.` is Dot.\n if matches!(self.peek_at(1), Some('0'..='9')) {\n self.scan_number()\n } else {\n self.bump();\n TokenKind::Dot\n }\n }\n '\\'' => self.scan_string(),\n '\"' => self.scan_quoted_identifier('\"', '\"'),\n '[' => self.scan_quoted_identifier('[', ']'),\n '`' => self.scan_quoted_identifier('`', '`'),\n '?' => self.scan_param_question(),\n ':' => self.scan_param_named(':'),\n '@' => self.scan_param_named('@'),\n '$' => self.scan_param_named('$'),\n c if c == 'x' || c == 'X' => self.scan_maybe_blob(c),\n c if is_ident_start(c) => self.scan_identifier_or_keyword(),\n _ => self.scan_operator(),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_783", + "id": "tokenizer_816", "file": "src/parser/tokenizer.rs", - "line": 783, + "line": 816, "decision": "c == 'x' || c == 'X'", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "tokenizer_784", + "id": "tokenizer_817", "file": "src/parser/tokenizer.rs", - "line": 784, + "line": 817, "decision": "is_ident_start(c)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_768", + "id": "tokenizer_801", "file": "src/parser/tokenizer.rs", - "line": 768, + "line": 801, "decision": "matches!(self.peek_at(1), Some('0'..='9'))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_797", + "id": "tokenizer_830", "file": "src/parser/tokenizer.rs", - "line": 797, + "line": 830, "decision": "is_ident_continue(c)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_810", + "id": "tokenizer_843", "file": "src/parser/tokenizer.rs", - "line": 810, + "line": 843, "decision": "self.peek_at(1) == Some('\\'')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_815", + "id": "tokenizer_848", "file": "src/parser/tokenizer.rs", - "line": 815, - "decision": "match self.peek_char() {\n None => {\n return TokenKind::Error(format!(\n \"unterminated blob literal starting with {x}'\"\n ));\n }\n Some('\\'') => {\n self.bump();\n break;\n }\n Some(c) => {\n hex.push(c);\n self.bump();\n }\n }", + "line": 848, + "decision": "match self.peek_char() {\n None => {\n return TokenKind::Error(format!(\n \"unterminated blob literal starting with {x}'\"\n ));\n }\n Some('\\'') => {\n break;\n }\n Some(_) => {\n self.bump();\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_831", + "id": "tokenizer_864", "file": "src/parser/tokenizer.rs", - "line": 831, + "line": 864, "decision": "!hex.len().is_multiple_of(2) || !hex.chars().all(|c| c.is_ascii_hexdigit())", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "tokenizer_837", + "id": "tokenizer_872", "file": "src/parser/tokenizer.rs", - "line": 837, - "decision": "match u8::from_str_radix(pair, 16) {\n Ok(b) => bytes.push(b),\n Err(_) => return TokenKind::Error(format!(\"invalid blob byte: {pair:?}\")),\n }", + "line": 872, + "decision": "match u8::from_str_radix(pair, 16) {\n Ok(b) => bytes.push(b),\n Err(_) => {\n let msg = format!(\"invalid blob byte: {pair:?}\");\n self.bump(); // closing '\n return TokenKind::Error(msg);\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_852", + "id": "tokenizer_896", "file": "src/parser/tokenizer.rs", - "line": 852, - "decision": "match self.peek_char() {\n None => return TokenKind::Error(\"unterminated string literal\".to_string()),\n Some('\\'') => {\n self.bump();\n if self.peek_char() == Some('\\'') {\n value.push('\\'');\n self.bump();\n } else {\n break;\n }\n }\n Some(c) => {\n value.push(c);\n self.bump();\n }\n }", + "line": 896, + "decision": "match self.peek_char() {\n None => return TokenKind::Error(\"unterminated string literal\".to_string()),\n Some('\\'') => {\n let quote_pos = self.pos;\n self.bump(); // consume this quote\n if self.peek_char() == Some('\\'') {\n let seg = self.src.get(seg_start..quote_pos).unwrap_or(\"\");\n let buf = acc.get_or_insert_with(String::new);\n buf.push_str(seg);\n buf.push('\\'');\n self.bump(); // consume the second quote\n seg_start = self.pos;\n } else {\n let seg = self.src.get(seg_start..quote_pos).unwrap_or(\"\");\n return TokenKind::String(match acc {\n Some(mut buf) => {\n buf.push_str(seg);\n buf\n }\n None => seg.to_string(),\n });\n }\n }\n Some(_) => {\n self.bump();\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_856", + "id": "tokenizer_901", "file": "src/parser/tokenizer.rs", - "line": 856, + "line": 901, "decision": "self.peek_char() == Some('\\'')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_880", + "id": "tokenizer_910", "file": "src/parser/tokenizer.rs", - "line": 880, - "decision": "match self.peek_char() {\n None => {\n return TokenKind::Error(format!(\n \"unterminated quoted identifier starting with {open:?}\"\n ));\n }\n Some(c) if c == close => {\n self.bump();\n if escapes && self.peek_char() == Some(close) {\n value.push(close);\n self.bump();\n } else {\n break;\n }\n }\n Some(c) => {\n value.push(c);\n self.bump();\n }\n }", + "line": 910, + "decision": "match acc {\n Some(mut buf) => {\n buf.push_str(seg);\n buf\n }\n None => seg.to_string(),\n }", + "conditions": 0, + "vectors_required": 0, + "compiler_void": true + }, + { + "id": "tokenizer_935", + "file": "src/parser/tokenizer.rs", + "line": 935, + "decision": "match self.peek_char() {\n None => {\n return TokenKind::Error(format!(\n \"unterminated quoted identifier starting with {open:?}\"\n ));\n }\n Some(c) if c == close => {\n let close_pos = self.pos;\n self.bump(); // consume this closing delimiter\n if escapes && self.peek_char() == Some(close) {\n let seg = self.src.get(seg_start..close_pos).unwrap_or(\"\");\n let buf = acc.get_or_insert_with(String::new);\n buf.push_str(seg);\n buf.push(close);\n self.bump(); // consume the doubled delimiter\n seg_start = self.pos;\n } else {\n let seg = self.src.get(seg_start..close_pos).unwrap_or(\"\");\n return TokenKind::Identifier(match acc {\n Some(mut buf) => {\n buf.push_str(seg);\n buf\n }\n None => seg.to_string(),\n });\n }\n }\n Some(_) => {\n self.bump();\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_886", + "id": "tokenizer_941", "file": "src/parser/tokenizer.rs", - "line": 886, + "line": 941, "decision": "c == close", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_888", + "id": "tokenizer_944", "file": "src/parser/tokenizer.rs", - "line": 888, + "line": 944, "decision": "escapes && self.peek_char() == Some(close)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "tokenizer_911", + "id": "tokenizer_953", "file": "src/parser/tokenizer.rs", - "line": 911, + "line": 953, + "decision": "match acc {\n Some(mut buf) => {\n buf.push_str(seg);\n buf\n }\n None => seg.to_string(),\n }", + "conditions": 0, + "vectors_required": 0, + "compiler_void": true + }, + { + "id": "tokenizer_972", + "file": "src/parser/tokenizer.rs", + "line": 972, + "decision": "matches!(self.peek_char(), Some('0'..='9'))", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "tokenizer_976", + "file": "src/parser/tokenizer.rs", + "line": 976, "decision": "digits.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_914", + "id": "tokenizer_979", "file": "src/parser/tokenizer.rs", - "line": 914, - "decision": "match digits.parse::() {\n Ok(n) => TokenKind::Param(Param::Numbered(n)),\n Err(_) => TokenKind::Error(format!(\"parameter number out of range: {digits}\")),\n }", + "line": 979, + "decision": "match digits.parse::() {\n Ok(n) => TokenKind::Param(Box::new(Param::Numbered(n))),\n Err(_) => TokenKind::Error(format!(\"parameter number out of range: {digits}\")),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_925", + "id": "tokenizer_990", "file": "src/parser/tokenizer.rs", - "line": 925, + "line": 990, "decision": "is_ident_continue(c)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_932", + "id": "tokenizer_997", "file": "src/parser/tokenizer.rs", - "line": 932, + "line": 997, "decision": "name.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_935", + "id": "tokenizer_1001", "file": "src/parser/tokenizer.rs", - "line": 935, - "decision": "match sigil {\n ':' => TokenKind::Param(Param::Colon(name)),\n '@' => TokenKind::Param(Param::At(name)),\n '$' => TokenKind::Param(Param::Dollar(name)),\n _ => TokenKind::Error(format!(\"unsupported parameter sigil {sigil:?}\")),\n }", + "line": 1001, + "decision": "match sigil {\n ':' => TokenKind::Param(Box::new(Param::Colon(name))),\n '@' => TokenKind::Param(Box::new(Param::At(name))),\n '$' => TokenKind::Param(Box::new(Param::Dollar(name))),\n _ => TokenKind::Error(format!(\"unsupported parameter sigil {sigil:?}\")),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_947", + "id": "tokenizer_1013", "file": "src/parser/tokenizer.rs", - "line": 947, + "line": 1013, "decision": "self.peek_char() == Some('0') && matches!(self.peek_at(1), Some('x' | 'X'))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "tokenizer_952", + "id": "tokenizer_1017", "file": "src/parser/tokenizer.rs", - "line": 952, - "decision": "c.is_ascii_hexdigit()", + "line": 1017, + "decision": "matches!(self.peek_char(), Some(c) if c.is_ascii_hexdigit())", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_959", + "id": "tokenizer_1021", "file": "src/parser/tokenizer.rs", - "line": 959, + "line": 1021, "decision": "hex.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_966", + "id": "tokenizer_1028", "file": "src/parser/tokenizer.rs", - "line": 966, - "decision": "match i64::from_str_radix(&hex, 16) {\n Ok(n) => TokenKind::Integer(n),\n Err(_) => match u64::from_str_radix(&hex, 16) {\n Ok(n) => TokenKind::Integer(n as i64),\n Err(e) => TokenKind::Error(format!(\"invalid hex literal: {e}\")),\n },\n }", + "line": 1028, + "decision": "match i64::from_str_radix(hex, 16) {\n Ok(n) => TokenKind::Integer(n),\n Err(_) => match u64::from_str_radix(hex, 16) {\n Ok(n) => TokenKind::Integer(n as i64),\n Err(e) => TokenKind::Error(format!(\"invalid hex literal: {e}\")),\n },\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_968", + "id": "tokenizer_1030", "file": "src/parser/tokenizer.rs", - "line": 968, - "decision": "match u64::from_str_radix(&hex, 16) {\n Ok(n) => TokenKind::Integer(n as i64),\n Err(e) => TokenKind::Error(format!(\"invalid hex literal: {e}\")),\n }", + "line": 1030, + "decision": "match u64::from_str_radix(hex, 16) {\n Ok(n) => TokenKind::Integer(n as i64),\n Err(e) => TokenKind::Error(format!(\"invalid hex literal: {e}\")),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_980", + "id": "tokenizer_1037", "file": "src/parser/tokenizer.rs", - "line": 980, + "line": 1037, + "decision": "matches!(self.peek_char(), Some('0'..='9'))", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "tokenizer_1041", + "file": "src/parser/tokenizer.rs", + "line": 1041, "decision": "self.peek_char() == Some('.')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_990", + "id": "tokenizer_1044", "file": "src/parser/tokenizer.rs", - "line": 990, + "line": 1044, + "decision": "matches!(self.peek_char(), Some('0'..='9'))", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "tokenizer_1049", + "file": "src/parser/tokenizer.rs", + "line": 1049, "decision": "matches!(self.peek_char(), Some('e' | 'E'))", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_992", + "id": "tokenizer_1051", "file": "src/parser/tokenizer.rs", - "line": 992, + "line": 1051, "decision": "sign_char", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_994", + "id": "tokenizer_1053", "file": "src/parser/tokenizer.rs", - "line": 994, + "line": 1053, "decision": "has_exp_digits", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_997", + "id": "tokenizer_1056", "file": "src/parser/tokenizer.rs", - "line": 997, + "line": 1056, "decision": "sign_char", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1007", + "id": "tokenizer_1059", + "file": "src/parser/tokenizer.rs", + "line": 1059, + "decision": "matches!(self.peek_char(), Some('0'..='9'))", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "tokenizer_1066", "file": "src/parser/tokenizer.rs", - "line": 1007, + "line": 1066, "decision": "is_float", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1008", + "id": "tokenizer_1067", "file": "src/parser/tokenizer.rs", - "line": 1008, + "line": 1067, "decision": "match text.parse::() {\n Ok(f) => TokenKind::Float(f),\n Err(e) => TokenKind::Error(format!(\"invalid float literal {text:?}: {e}\")),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1013", + "id": "tokenizer_1072", "file": "src/parser/tokenizer.rs", - "line": 1013, + "line": 1072, "decision": "match text.parse::() {\n Ok(n) => TokenKind::Integer(n),\n Err(_) => match text.parse::() {\n Ok(f) => TokenKind::Float(f),\n Err(e) => TokenKind::Error(format!(\"invalid integer literal {text:?}: {e}\")),\n },\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1015", + "id": "tokenizer_1074", "file": "src/parser/tokenizer.rs", - "line": 1015, + "line": 1074, "decision": "match text.parse::() {\n Ok(f) => TokenKind::Float(f),\n Err(e) => TokenKind::Error(format!(\"invalid integer literal {text:?}: {e}\")),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1024", + "id": "tokenizer_1083", "file": "src/parser/tokenizer.rs", - "line": 1024, + "line": 1083, "decision": "match self.bump() {\n Some(c) => c,\n None => return TokenKind::Eof,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1028", + "id": "tokenizer_1087", "file": "src/parser/tokenizer.rs", - "line": 1028, + "line": 1087, "decision": "match c {\n '*' => TokenKind::Star,\n ',' => TokenKind::Comma,\n ';' => TokenKind::Semicolon,\n '(' => TokenKind::LParen,\n ')' => TokenKind::RParen,\n '+' => TokenKind::Plus,\n '/' => TokenKind::Slash,\n '%' => TokenKind::Percent,\n '~' => TokenKind::BitNot,\n '-' => {\n if self.peek_char() == Some('>') {\n self.bump();\n if self.peek_char() == Some('>') {\n self.bump();\n TokenKind::ArrowArrow\n } else {\n TokenKind::Arrow\n }\n } else {\n TokenKind::Minus\n }\n }\n '=' => {\n if self.peek_char() == Some('=') {\n self.bump();\n }\n TokenKind::Eq\n }\n '!' => {\n if self.peek_char() == Some('=') {\n self.bump();\n TokenKind::Ne\n } else {\n TokenKind::Error(\"expected '=' after '!'\".to_string())\n }\n }\n '<' => match self.peek_char() {\n Some('=') => {\n self.bump();\n TokenKind::Le\n }\n Some('>') => {\n self.bump();\n TokenKind::Ne\n }\n Some('<') => {\n self.bump();\n TokenKind::Shl\n }\n _ => TokenKind::Lt,\n },\n '>' => match self.peek_char() {\n Some('=') => {\n self.bump();\n TokenKind::Ge\n }\n Some('>') => {\n self.bump();\n TokenKind::Shr\n }\n _ => TokenKind::Gt,\n },\n '|' => {\n if self.peek_char() == Some('|') {\n self.bump();\n TokenKind::Concat\n } else {\n TokenKind::BitOr\n }\n }\n '&' => TokenKind::BitAnd,\n other => TokenKind::Error(format!(\"unexpected character {other:?}\")),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1039", + "id": "tokenizer_1098", "file": "src/parser/tokenizer.rs", - "line": 1039, + "line": 1098, "decision": "self.peek_char() == Some('>')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1041", + "id": "tokenizer_1100", "file": "src/parser/tokenizer.rs", - "line": 1041, + "line": 1100, "decision": "self.peek_char() == Some('>')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1052", + "id": "tokenizer_1111", "file": "src/parser/tokenizer.rs", - "line": 1052, + "line": 1111, "decision": "self.peek_char() == Some('=')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1058", + "id": "tokenizer_1117", "file": "src/parser/tokenizer.rs", - "line": 1058, + "line": 1117, "decision": "self.peek_char() == Some('=')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1065", + "id": "tokenizer_1124", "file": "src/parser/tokenizer.rs", - "line": 1065, + "line": 1124, "decision": "match self.peek_char() {\n Some('=') => {\n self.bump();\n TokenKind::Le\n }\n Some('>') => {\n self.bump();\n TokenKind::Ne\n }\n Some('<') => {\n self.bump();\n TokenKind::Shl\n }\n _ => TokenKind::Lt,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1080", + "id": "tokenizer_1139", "file": "src/parser/tokenizer.rs", - "line": 1080, + "line": 1139, "decision": "match self.peek_char() {\n Some('=') => {\n self.bump();\n TokenKind::Ge\n }\n Some('>') => {\n self.bump();\n TokenKind::Shr\n }\n _ => TokenKind::Gt,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1092", + "id": "tokenizer_1151", "file": "src/parser/tokenizer.rs", - "line": 1092, + "line": 1151, "decision": "self.peek_char() == Some('|')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "tokenizer_1131", + "id": "tokenizer_1190", "file": "src/parser/tokenizer.rs", - "line": 1131, - "decision": "match tok.kind {\n TokenKind::Semicolon => {\n let end = tok.span.offset as usize;\n push_trimmed(&mut statements, &sql[start..end]);\n start = (tok.span.offset as usize).saturating_add(tok.span.len as usize);\n }\n TokenKind::Eof => {\n push_trimmed(&mut statements, &sql[start..]);\n }\n _ => {}\n }", + "line": 1190, + "decision": "match tok.kind {\n TokenKind::Semicolon => {\n let end = tok.span.offset as usize;\n push_trimmed(&mut statements, sql.get(start..end).unwrap_or(\"\"));\n start = (tok.span.offset as usize).saturating_add(tok.span.len as usize);\n }\n TokenKind::Eof => {\n push_trimmed(&mut statements, sql.get(start..).unwrap_or(\"\"));\n }\n _ => {}\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "tokenizer_1148", + "id": "tokenizer_1207", "file": "src/parser/tokenizer.rs", - "line": 1148, + "line": 1207, "decision": "!trimmed.is_empty()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_146", + "id": "exec_148", "file": "src/vdbe/exec.rs", - "line": 146, + "line": 148, "decision": "match self {\n ExecError::RegisterOutOfRange { opcode, index } => {\n write!(f, \"{opcode}: register index {index} is out of range\")\n }\n ExecError::RegisterRangeTooLarge { opcode, count } => write!(\n f,\n \"{opcode}: register range count {count} exceeds the maximum ({MAX_REGISTERS})\"\n ),\n ExecError::TypeMismatch { opcode, found } => {\n write!(\n f,\n \"{opcode}: expected a different value type, found {found}\"\n )\n }\n ExecError::MustBeInt => write!(\n f,\n \"MustBeInt: value cannot be converted to an integer without data loss\"\n ),\n ExecError::MalformedInstruction { opcode, reason } => {\n write!(f, \"{opcode}: malformed instruction ({reason})\")\n }\n ExecError::Unimplemented { opcode } => {\n write!(f, \"opcode {opcode:?} is not yet implemented by this VM\")\n }\n ExecError::CursorNotOpen { slot } => write!(f, \"cursor slot {slot} is not open\"),\n ExecError::CursorTypeMismatch {\n opcode,\n slot,\n found,\n expected,\n } => write!(\n f,\n \"{opcode}: cursor slot {slot} is a {found}, not a {expected}\"\n ),\n ExecError::NoDatabase { opcode } => write!(\n f,\n \"{opcode} requires a database attached to this VM (see Vm::with_db)\"\n ),\n ExecError::ProgramCounterOutOfRange { pc } => {\n write!(f, \"program counter {pc} is out of range\")\n }\n ExecError::StepLimitExceeded => write!(\n f,\n \"program exceeded the maximum step count ({MAX_STEPS}) without halting\"\n ),\n ExecError::EphemeralRowLimitExceeded { opcode, limit } => write!(\n f,\n \"{opcode}: ephemeral table/index exceeded the maximum row count ({limit})\"\n ),\n ExecError::Halted { code, message } => write!(\n f,\n \"statement halted with SQLite result code {code}{}\",\n message\n .as_deref()\n .map(|m| format!(\": {m}\"))\n .unwrap_or_default()\n ),\n ExecError::FlushFailed(e) => {\n write!(f, \"failed to flush pending writes on statement commit: {e}\")\n }\n ExecError::TransactionAlreadyActive => {\n write!(f, \"cannot start a transaction within a transaction\")\n }\n ExecError::NoActiveTransactionToCommit => {\n write!(f, \"cannot commit - no transaction is active\")\n }\n ExecError::NoActiveTransactionToRollback => {\n write!(f, \"cannot rollback - no transaction is active\")\n }\n ExecError::JournalModeChangeDuringTransaction => {\n write!(f, \"cannot change journal_mode within a transaction\")\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_224", + "id": "exec_226", "file": "src/vdbe/exec.rs", - "line": 224, + "line": 226, "decision": "match self {\n ExecError::FlushFailed(e) => Some(e),\n _ => None,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_453", + "id": "exec_444", "file": "src/vdbe/exec.rs", - "line": 453, + "line": 444, "decision": "reg < 0 || reg as usize > MAX_REGISTERS", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "exec_463", + "id": "exec_455", "file": "src/vdbe/exec.rs", - "line": 463, + "line": 455, "decision": "!(0..=MAX_REGISTERS as i32).contains(&count)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_482", + "id": "exec_476", "file": "src/vdbe/exec.rs", - "line": 482, + "line": 476, "decision": "idx >= self.registers.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_515", + "id": "exec_510", "file": "src/vdbe/exec.rs", - "line": 515, + "line": 510, "decision": "match self.registers.get_mut(idx) {\n Some(slot) => std::mem::replace(slot, Value::Null),\n None => Value::Null,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_548", + "id": "exec_543", "file": "src/vdbe/exec.rs", - "line": 548, + "line": 543, "decision": "idx >= self.cursors.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_582", + "id": "exec_577", "file": "src/vdbe/exec.rs", - "line": 582, + "line": 577, "decision": "idx >= self.agg_contexts.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_616", + "id": "exec_611", "file": "src/vdbe/exec.rs", - "line": 616, + "line": 611, "decision": "idx >= self.filters.len()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_669", + "id": "exec_664", "file": "src/vdbe/exec.rs", - "line": 669, + "line": 664, "decision": "matches!(a, Value::Null) || matches!(b, Value::Null)", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "exec_672", + "id": "exec_667", "file": "src/vdbe/exec.rs", - "line": 672, + "line": 667, "decision": "match &instr.p4 {\n P4::CollSeq {\n collation,\n affinity,\n } => (*collation, Affinity::from_p4_byte(*affinity)),\n _ => (Collation::Binary, Affinity::Blob),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_684", + "id": "exec_679", "file": "src/vdbe/exec.rs", - "line": 684, + "line": 679, "decision": "matches!(affinity, Affinity::Blob)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_693", + "id": "exec_688", "file": "src/vdbe/exec.rs", - "line": 693, + "line": 688, "decision": "holds(ord)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_740", + "id": "exec_736", "file": "src/vdbe/exec.rs", - "line": 740, - "decision": "match instr.opcode {\n Init => control::init(instr),\n Goto => control::goto(instr),\n Once => control::once(vm, pc, instr),\n BeginSubrtn => control::begin_subrtn(),\n Return => control::r#return(vm, instr),\n Halt => control::halt(instr),\n Transaction => control::transaction(vm, instr),\n AutoCommit => control::auto_commit(vm, instr),\n SetJournalMode => pragma::set_journal_mode(vm, instr),\n IntegrityCheck => pragma::integrity_check(vm, instr),\n IfNot => control::if_not(vm, instr),\n IfNotZero => control::if_not_zero(vm, instr),\n IfPos => control::if_pos(vm, instr),\n DecrJumpZero => control::decr_jump_zero(vm, instr),\n IsNull => control::is_null(vm, instr),\n NotNull => control::not_null(vm, instr),\n MustBeInt => control::must_be_int(vm, instr),\n OffsetLimit => control::offset_limit(vm, instr),\n\n Eq => compare_jump(vm, instr, |o| o == Ordering::Equal),\n Ge => compare_jump(vm, instr, |o| o != Ordering::Less),\n Gt => compare_jump(vm, instr, |o| o == Ordering::Greater),\n Le => compare_jump(vm, instr, |o| o != Ordering::Greater),\n Lt => compare_jump(vm, instr, |o| o == Ordering::Less),\n RealAffinity => real_affinity(vm, instr),\n Cast => cast(vm, instr),\n\n Add => arithmetic::add(vm, instr),\n Subtract => arithmetic::subtract(vm, instr),\n Multiply => arithmetic::multiply(vm, instr),\n Divide => arithmetic::divide(vm, instr),\n Remainder => arithmetic::remainder(vm, instr),\n Not => arithmetic::not(vm, instr),\n BitAnd => arithmetic::bit_and(vm, instr),\n BitOr => arithmetic::bit_or(vm, instr),\n ShiftLeft => arithmetic::shift_left(vm, instr),\n ShiftRight => arithmetic::shift_right(vm, instr),\n BitNot => arithmetic::bit_not(vm, instr),\n Concat => arithmetic::concat(vm, instr),\n\n Integer => result::integer(vm, instr),\n Int64 => result::int64(vm, instr),\n Real => result::real(vm, instr),\n Blob => result::blob(vm, instr),\n Null => result::null(vm, instr),\n String8 => result::string8(vm, instr),\n Variable => result::variable(vm, instr),\n MakeRecord => result::make_record(vm, instr),\n ResultRow => result::result_row(vm, instr),\n Copy => result::copy(vm, instr),\n\n OpenRead => cursor::open_read(vm, instr),\n OpenWrite => cursor::open_write(vm, instr),\n OpenEphemeral => cursor::open_ephemeral(vm, instr),\n OpenDup => cursor::open_dup(vm, instr),\n OpenPseudo => cursor::open_pseudo(vm, instr),\n Rewind => cursor::rewind(vm, instr),\n Last => cursor::last(vm, instr),\n Next => cursor::next(vm, instr),\n Column => cursor::column(vm, instr),\n Rowid => cursor::rowid(vm, instr),\n SeekRowid => cursor::seek_rowid(vm, instr),\n SeekIndexEq => cursor::seek_index_eq(vm, instr),\n IdxRowid => cursor::idx_rowid(vm, instr),\n IdxRewind => cursor::idx_rewind(vm, instr),\n IdxLast => cursor::idx_last(vm, instr),\n IdxNext => cursor::idx_next(vm, instr),\n IdxPrev => cursor::idx_prev(vm, instr),\n NullRow => cursor::null_row(vm, instr),\n Sequence => cursor::sequence(vm, instr),\n Found => cursor::found(vm, instr),\n IdxInsert => cursor::idx_insert(vm, instr),\n IdxDelete => cursor::idx_delete(vm, instr),\n Count => cursor::count(vm, instr),\n AutoIndexInsert => cursor::auto_index_insert(vm, instr),\n AutoIndexSeek => cursor::auto_index_seek(vm, instr),\n AutoIndexRowid => cursor::auto_index_rowid(vm, instr),\n AutoIndexNext => cursor::auto_index_next(vm, instr),\n IdxLE => cursor::idx_le(vm, instr),\n NoConflict => cursor::no_conflict(vm, instr),\n Delete => cursor::delete(vm, instr),\n Insert => cursor::insert(vm, instr),\n NewRowid => cursor::new_rowid(vm, instr),\n CreateTable => cursor::create_table(vm, instr),\n CreateView => cursor::create_view(vm, instr),\n DropTable => cursor::drop_table(vm, instr),\n CreateIndex => cursor::create_index(vm, instr),\n DropIndex => cursor::drop_index(vm, instr),\n Analyze => cursor::analyze(vm, instr),\n\n SorterOpen => sorter::sorter_open(vm, instr),\n SorterInsert => sorter::sorter_insert(vm, instr),\n SorterSort | Sort => sorter::sorter_sort(vm, instr),\n SorterNext => sorter::sorter_next(vm, instr),\n SorterData => sorter::sorter_data(vm, instr),\n\n Function => function(vm, instr),\n AggStep => agg_step(vm, instr),\n AggFinal => agg_final(vm, instr),\n\n FilterAdd => filter_add(vm, instr),\n Filter => filter_check(vm, instr),\n }", + "line": 736, + "decision": "match instr.opcode {\n Init => control::init(instr),\n Goto => control::goto(instr),\n Once => control::once(vm, pc, instr),\n BeginSubrtn => control::begin_subrtn(),\n Return => control::r#return(vm, instr),\n Halt => control::halt(instr),\n Transaction => control::transaction(vm, instr),\n AutoCommit => control::auto_commit(vm, instr),\n SetJournalMode => pragma::set_journal_mode(vm, instr),\n IntegrityCheck => pragma::integrity_check(vm, instr),\n IfNot => control::if_not(vm, instr),\n IfNotZero => control::if_not_zero(vm, instr),\n IfPos => control::if_pos(vm, instr),\n DecrJumpZero => control::decr_jump_zero(vm, instr),\n IsNull => control::is_null(vm, instr),\n NotNull => control::not_null(vm, instr),\n MustBeInt => control::must_be_int(vm, instr),\n OffsetLimit => control::offset_limit(vm, instr),\n\n Eq => compare_jump(vm, instr, |o| o == Ordering::Equal),\n Ge => compare_jump(vm, instr, |o| o != Ordering::Less),\n Gt => compare_jump(vm, instr, |o| o == Ordering::Greater),\n Le => compare_jump(vm, instr, |o| o != Ordering::Greater),\n Lt => compare_jump(vm, instr, |o| o == Ordering::Less),\n RealAffinity => real_affinity(vm, instr),\n Cast => cast(vm, instr),\n\n Add => arithmetic::add(vm, instr),\n Subtract => arithmetic::subtract(vm, instr),\n Multiply => arithmetic::multiply(vm, instr),\n Divide => arithmetic::divide(vm, instr),\n Remainder => arithmetic::remainder(vm, instr),\n Not => arithmetic::not(vm, instr),\n BitAnd => arithmetic::bit_and(vm, instr),\n BitOr => arithmetic::bit_or(vm, instr),\n ShiftLeft => arithmetic::shift_left(vm, instr),\n ShiftRight => arithmetic::shift_right(vm, instr),\n BitNot => arithmetic::bit_not(vm, instr),\n Concat => arithmetic::concat(vm, instr),\n\n Integer => result::integer(vm, instr),\n Int64 => result::int64(vm, instr),\n Real => result::real(vm, instr),\n Blob => result::blob(vm, instr),\n Null => result::null(vm, instr),\n String8 => result::string8(vm, instr),\n Variable => result::variable(vm, instr),\n MakeRecord => result::make_record(vm, instr),\n ResultRow => result::result_row(vm, instr),\n Copy => result::copy(vm, instr),\n\n OpenRead => cursor::open_read(vm, instr),\n OpenWrite => cursor::open_write(vm, instr),\n OpenEphemeral => cursor::open_ephemeral(vm, instr),\n OpenDup => cursor::open_dup(vm, instr),\n OpenPseudo => cursor::open_pseudo(vm, instr),\n Rewind => cursor::rewind(vm, instr),\n Last => cursor::last(vm, instr),\n Next => cursor::next(vm, instr),\n Column => cursor::column(vm, instr),\n Rowid => cursor::rowid(vm, instr),\n SeekRowid => cursor::seek_rowid(vm, instr),\n SeekIndexEq => cursor::seek_index_eq(vm, instr),\n IdxRowid => cursor::idx_rowid(vm, instr),\n IdxRewind => cursor::idx_rewind(vm, instr),\n IdxLast => cursor::idx_last(vm, instr),\n IdxNext => cursor::idx_next(vm, instr),\n IdxPrev => cursor::idx_prev(vm, instr),\n NullRow => cursor::null_row(vm, instr),\n Sequence => cursor::sequence(vm, instr),\n Found => cursor::found(vm, instr),\n IdxInsert => cursor::idx_insert(vm, instr),\n IdxDelete => cursor::idx_delete(vm, instr),\n Count => cursor::count(vm, instr),\n AutoIndexInsert => cursor::auto_index_insert(vm, instr),\n AutoIndexSeek => cursor::auto_index_seek(vm, instr),\n AutoIndexRowid => cursor::auto_index_rowid(vm, instr),\n AutoIndexNext => cursor::auto_index_next(vm, instr),\n IdxLE => cursor::idx_le(vm, instr),\n NoConflict => cursor::no_conflict(vm, instr),\n Delete => cursor::delete(vm, instr),\n Insert => cursor::insert(vm, instr),\n NewRowid => cursor::new_rowid(vm, instr),\n CreateTable => cursor::create_table(vm, instr),\n CreateView => cursor::create_view(vm, instr),\n DropTable => cursor::drop_table(vm, instr),\n CreateIndex => cursor::create_index(vm, instr),\n DropIndex => cursor::drop_index(vm, instr),\n Analyze => cursor::analyze(vm, instr),\n\n SorterOpen => sorter::sorter_open(vm, instr),\n SorterInsert => sorter::sorter_insert(vm, instr),\n SorterSort | Sort => sorter::sorter_sort(vm, instr),\n SorterNext => sorter::sorter_next(vm, instr),\n HashAggOpen => hash_agg::hash_agg_open(vm, instr),\n HashAggFind => hash_agg::hash_agg_find(vm, instr),\n HashAggStep => hash_agg::hash_agg_step(vm, instr),\n HashAggRewind => hash_agg::hash_agg_rewind(vm, instr),\n HashAggData => hash_agg::hash_agg_data(vm, instr),\n HashAggNext => hash_agg::hash_agg_next(vm, instr),\n SorterData => sorter::sorter_data(vm, instr),\n\n Function => function(vm, instr),\n AggStep => agg_step(vm, instr),\n AggFinal => agg_final(vm, instr),\n\n FilterAdd => filter_add(vm, instr),\n Filter => filter_check(vm, instr),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_850", + "id": "exec_852", "file": "src/vdbe/exec.rs", - "line": 850, + "line": 852, "decision": "match &instr.p4 {\n P4::Int(n) => u64::try_from(*n).unwrap_or(0),\n _ => 0,\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_864", + "id": "exec_866", "file": "src/vdbe/exec.rs", - "line": 864, + "line": 866, "decision": "vm.filter_might_contain(instr.p1, &value)?", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_878", + "id": "exec_880", "file": "src/vdbe/exec.rs", - "line": 878, + "line": 880, "decision": "match &instr.p4 {\n P4::Str(s) => s.as_str(),\n other => {\n return Err(ExecError::MalformedInstruction {\n opcode: \"Function\",\n reason: format!(\"expected a \\\"name(arity)\\\" string P4, got {other:?}\"),\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_930", + "id": "exec_932", "file": "src/vdbe/exec.rs", - "line": 930, + "line": 932, "decision": "match &instr.p4 {\n P4::AggFunc {\n name,\n arity,\n collation,\n } => (name.as_str(), *arity, *collation),\n other => {\n return Err(ExecError::MalformedInstruction {\n opcode: \"AggStep\",\n reason: format!(\"expected an AggFunc P4, got {other:?}\"),\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_959", + "id": "exec_961", "file": "src/vdbe/exec.rs", - "line": 959, + "line": 961, "decision": "instr.p5 == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_994", + "id": "exec_996", "file": "src/vdbe/exec.rs", - "line": 994, + "line": 996, "decision": "match &instr.p4 {\n P4::Str(s) => s.as_str(),\n other => {\n return Err(ExecError::MalformedInstruction {\n opcode: \"AggFinal\",\n reason: format!(\"expected a \\\"name(arity)\\\" string P4, got {other:?}\"),\n })\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_1024", + "id": "exec_1026", "file": "src/vdbe/exec.rs", - "line": 1024, + "line": 1026, "decision": "!descriptor.ends_with(')')", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_1137", + "id": "exec_1139", "file": "src/vdbe/exec.rs", - "line": 1137, + "line": 1139, "decision": "steps > MAX_STEPS", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "exec_1143", + "id": "exec_1145", "file": "src/vdbe/exec.rs", - "line": 1143, + "line": 1145, "decision": "match dispatch(&mut vm, pc, instr)? {\n Step::Next => {\n pc = pc.saturating_add(1);\n }\n Step::Jump(target) => pc = target,\n Step::Halt { code: 0, .. } => {\n // A program with no explicit `Transaction` (#194's\n // original behavior, unchanged) treats a successful\n // `Halt` as an implicit commit, flushing any pending\n // write-opcode changes before returning. A `Vm::with_db`\n // (read-only) or a writable `Vm` that never actually\n // wrote anything both take the cheap\n // `writer.is_none()`/`dirty.is_empty()` no-op path.\n //\n // #360: a program that opened an explicit transaction\n // (`Transaction` opcode, `vm.autocommit == false`) and\n // hasn't reached a matching `AutoCommit` yet does\n // neither — one SQL statement is one `Program`/`Vm`\n // (see `execute_transaction_step`), so `BEGIN`'s own\n // `Halt` running with `autocommit == false` is the\n // normal, expected case: the transaction stays open,\n // `vm.autocommit` carries that forward to whichever\n // `Vm` runs the next statement on this same `Pager`.\n if let Some(db) = &vm.db {\n if vm.autocommit {\n if let Some(writer) = &db.writer {\n writer.borrow_mut().flush()?;\n }\n }\n }\n return Ok((vm.rows, vm.autocommit));\n }\n Step::Halt { code, message } => return Err(ExecError::Halted { code, message }),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "exec_1167", + "id": "exec_1169", "file": "src/vdbe/exec.rs", - "line": 1167, + "line": 1169, "decision": "vm.autocommit", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_15", + "id": "encode_31", "file": "src/record/encode.rs", - "line": 15, + "line": 31, "decision": "value < (1u64 << 56)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_17", + "id": "encode_33", "file": "src/record/encode.rs", - "line": 17, + "line": 33, "decision": "groups < 8 && value >= (1u64 << (7 * groups))", "conditions": 2, "vectors_required": 3, "compiler_void": false }, { - "id": "encode_25", + "id": "encode_40", "file": "src/record/encode.rs", - "line": 25, + "line": 40, "decision": "i != groups - 1", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_56", + "id": "encode_66", + "file": "src/record/encode.rs", + "line": 66, + "decision": "value < (1u64 << 56)", + "conditions": 1, + "vectors_required": 2, + "compiler_void": false + }, + { + "id": "encode_68", + "file": "src/record/encode.rs", + "line": 68, + "decision": "groups < 8 && value >= (1u64 << (7 * groups))", + "conditions": 2, + "vectors_required": 3, + "compiler_void": false + }, + { + "id": "encode_86", "file": "src/record/encode.rs", - "line": 56, + "line": 86, "decision": "i == 0", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_58", + "id": "encode_88", "file": "src/record/encode.rs", - "line": 58, + "line": 88, "decision": "i == 1", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_60", + "id": "encode_90", "file": "src/record/encode.rs", - "line": 60, + "line": 90, "decision": "i8::try_from(i).is_ok()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_62", + "id": "encode_92", "file": "src/record/encode.rs", - "line": 62, + "line": 92, "decision": "i16::try_from(i).is_ok()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_64", + "id": "encode_94", "file": "src/record/encode.rs", - "line": 64, + "line": 94, "decision": "(I24_MIN..=I24_MAX).contains(&i)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_66", + "id": "encode_96", "file": "src/record/encode.rs", - "line": 66, + "line": 96, "decision": "i32::try_from(i).is_ok()", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_68", + "id": "encode_98", "file": "src/record/encode.rs", - "line": 68, + "line": 98, "decision": "(I48_MIN..=I48_MAX).contains(&i)", "conditions": 1, "vectors_required": 2, "compiler_void": false }, { - "id": "encode_76", + "id": "encode_106", "file": "src/record/encode.rs", - "line": 76, - "decision": "match serial_type {\n 1 => vec![i as u8],\n 2 => (i as i16).to_be_bytes().to_vec(),\n 3 => {\n let b = i.to_be_bytes();\n b[5..8].to_vec()\n }\n 4 => (i as i32).to_be_bytes().to_vec(),\n 5 => {\n let b = i.to_be_bytes();\n b[2..8].to_vec()\n }\n 6 => i.to_be_bytes().to_vec(),\n _ => Vec::new(), // 8/9: zero-byte constants\n }", + "line": 106, + "decision": "match serial_type {\n 1 => 1,\n 2 => 2,\n 3 => 3,\n 4 => 4,\n 5 => 5,\n 6 => 8,\n _ => 0, // 8/9: zero-byte constants\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "encode_94", + "id": "encode_118", "file": "src/record/encode.rs", - "line": 94, - "decision": "match encoding {\n TextEncoding::Utf8 => s.as_bytes().to_vec(),\n TextEncoding::Utf16Le => s.encode_utf16().flat_map(|u| u.to_le_bytes()).collect(),\n TextEncoding::Utf16Be => s.encode_utf16().flat_map(|u| u.to_be_bytes()).collect(),\n }", + "line": 118, + "decision": "match serial_type {\n 1 => out.push(i as u8),\n 2 => out.extend_from_slice(&(i as i16).to_be_bytes()),\n 3 => out.extend_from_slice(&i.to_be_bytes()[5..8]),\n 4 => out.extend_from_slice(&(i as i32).to_be_bytes()),\n 5 => out.extend_from_slice(&i.to_be_bytes()[2..8]),\n 6 => out.extend_from_slice(&i.to_be_bytes()),\n _ => {} // 8/9: zero-byte constants\n }", + "conditions": 0, + "vectors_required": 0, + "compiler_void": true + }, + { + "id": "encode_132", + "file": "src/record/encode.rs", + "line": 132, + "decision": "match encoding {\n TextEncoding::Utf8 => s.len(),\n TextEncoding::Utf16Le | TextEncoding::Utf16Be => s.encode_utf16().count().saturating_mul(2),\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true }, { - "id": "encode_114", + "id": "encode_139", "file": "src/record/encode.rs", - "line": 114, - "decision": "match value {\n Value::Null => (0, Vec::new()),\n Value::Integer(i) => {\n let st = integer_serial_type(*i);\n (st, integer_body(*i, st))\n }\n Value::Real(r) => (7, r.to_be_bytes().to_vec()),\n Value::Blob(b) => (blob_serial_type(b.len()), b.to_vec()),\n Value::Text(s) => {\n let body = encode_text(s, encoding);\n (text_serial_type(body.len()), body)\n }\n }", + "line": 139, + "decision": "match encoding {\n TextEncoding::Utf8 => out.extend_from_slice(s.as_bytes()),\n TextEncoding::Utf16Le => {\n out.extend(s.encode_utf16().flat_map(|u| u.to_le_bytes()));\n }\n TextEncoding::Utf16Be => {\n out.extend(s.encode_utf16().flat_map(|u| u.to_be_bytes()));\n }\n }", "conditions": 0, "vectors_required": 0, "compiler_void": true @@ -4755,7 +4890,25 @@ "id": "encode_164", "file": "src/record/encode.rs", "line": 164, - "decision": "hl_bytes.len().saturating_add(serial_type_bytes.len()) == header_len", + "decision": "match value {\n Value::Null => (0, 0),\n Value::Integer(i) => {\n let st = integer_serial_type(*i);\n (st, integer_body_len(st))\n }\n Value::Real(_) => (7, 8),\n Value::Blob(b) => (blob_serial_type(b.len()), b.len()),\n Value::Text(s) => {\n let len = encoded_text_len(s, encoding);\n (text_serial_type(len), len)\n }\n }", + "conditions": 0, + "vectors_required": 0, + "compiler_void": true + }, + { + "id": "encode_180", + "file": "src/record/encode.rs", + "line": 180, + "decision": "match value {\n Value::Null => {}\n Value::Integer(i) => write_integer_body_into(*i, serial_type, out),\n Value::Real(r) => out.extend_from_slice(&r.to_be_bytes()),\n Value::Blob(b) => out.extend_from_slice(b),\n Value::Text(s) => write_text_body_into(s, encoding, out),\n }", + "conditions": 0, + "vectors_required": 0, + "compiler_void": true + }, + { + "id": "encode_232", + "file": "src/record/encode.rs", + "line": 232, + "decision": "varint_len(header_len as u64).saturating_add(header_body_len) != header_len", "conditions": 1, "vectors_required": 2, "compiler_void": false From 1ecbf22d90ee0ac82a60891cbf698f7eb1f7e0b3 Mon Sep 17 00:00:00 2001 From: Ilja Heitlager Date: Thu, 27 Aug 2026 22:56:20 +0200 Subject: [PATCH 3/3] docs: note MC/DC obligations refresh + fuzz fix under Unreleased Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8e3fe5c..96fe9b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,24 @@ All notable changes to sqlite-rs. Format follows [Keep a Changelog](https://keep `CodegenError::CircularView`, `src/vdbe/collation.rs` → `src/record/collation.rs`, and three `path:line` citations in 011. +### Fix + +- `tests/fuzz/fuzz_targets/btree_cursor.rs`'s `FuzzPageSource` implemented + the pre-`Rc<[u8]>` `PageSource::read_page` signature, breaking + `make fuzz-btree`. Updated to return `Rc<[u8]>`. + +### Chore + +- Regenerated the MC/DC obligations snapshot (`tests/mcdc/obligations.json`) + and renamed every `mcdc____vN` tagged test (plus doc-comment + cross-references) to the obligation id its decision now resolves to, + across `src/btree.rs`, `src/btree/index.rs`, `src/btree/table/delete.rs`, + `src/parser/grammar.rs`, `src/parser/tokenizer.rs`, `src/record/encode.rs`, + `src/vdbe/exec.rs`, `src/vdbe/functions.rs` — the ids had drifted from + source line numbers, silently reducing real MC/DC discharge on the + scanned file set to near zero. Now correctly reports 40/42 real MC/DC + obligations discharged; `btree_966` and `encode_68` remain undischarged. + ## [0.18.5] - 2026-08-27 ### Chore