@feltdb/core 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/dist/cli/commands.js +4 -1
  2. package/dist/cli/provisioning-neutrality.js +79 -0
  3. package/dist/collection.d.ts +43 -1
  4. package/dist/collection.d.ts.map +1 -1
  5. package/dist/collection.js +192 -22
  6. package/dist/create/create.js +25 -21
  7. package/dist/create/managed-account.js +11 -0
  8. package/dist/create/package-versions.js +1 -1
  9. package/dist/create/server-source/Cargo.lock +165 -0
  10. package/dist/create/server-source/Cargo.toml +9 -0
  11. package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
  12. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
  13. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
  14. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
  15. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
  16. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
  17. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
  18. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
  19. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
  20. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
  21. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
  22. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
  23. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
  24. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
  25. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
  26. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
  27. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
  28. package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
  29. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
  30. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
  31. package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
  32. package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
  33. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
  34. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
  35. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
  36. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
  37. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
  38. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
  39. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
  40. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
  41. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
  42. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
  43. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
  44. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
  45. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
  46. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
  47. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
  48. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
  49. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
  50. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
  51. package/dist/create/server-source/crates/feltdb/src/equality_index.rs +595 -0
  52. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
  53. package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
  54. package/dist/create/server-source/crates/feltdb/src/lib.rs +1050 -117
  55. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
  56. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
  57. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
  58. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
  59. package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
  60. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
  61. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
  62. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
  63. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
  64. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
  65. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
  66. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
  67. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
  68. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
  69. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
  70. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +90 -72
  71. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
  72. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
  73. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
  74. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
  75. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
  76. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
  77. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
  78. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
  79. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
  80. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
  81. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
  82. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
  83. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
  84. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
  85. package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
  86. package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +126 -0
  87. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
  88. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
  89. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
  90. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
  91. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
  92. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
  93. package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
  94. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
  95. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +305 -6
  96. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
  97. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
  98. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
  99. package/dist/create/server-source/crates/feltdb/src/state_model.rs +1514 -537
  100. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
  101. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
  102. package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
  103. package/dist/create/server-source/crates/feltdb/src/sync.rs +12 -0
  104. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
  105. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
  106. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
  107. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
  108. package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
  109. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
  110. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
  111. package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
  112. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +442 -0
  113. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
  114. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +288 -0
  115. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
  116. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
  117. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
  118. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
  119. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
  120. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +234 -0
  121. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +947 -0
  122. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
  123. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
  124. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
  125. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
  126. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
  127. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
  128. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
  129. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
  130. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
  131. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1032 -0
  132. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
  133. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
  134. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
  135. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
  136. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
  137. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
  138. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
  139. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
  140. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
  141. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
  142. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
  143. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
  144. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
  145. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
  146. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
  147. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
  148. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +2 -1
  149. package/dist/create/server-source/crates/feltdb-server/src/audit.rs +1137 -29
  150. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
  151. package/dist/create/server-source/crates/feltdb-server/src/main.rs +800 -34
  152. package/dist/db.d.ts +33 -34
  153. package/dist/db.d.ts.map +1 -1
  154. package/dist/db.js +74 -20
  155. package/dist/deployment.d.ts +30 -0
  156. package/dist/deployment.d.ts.map +1 -0
  157. package/dist/deployment.js +130 -0
  158. package/dist/embedded-transaction.d.ts +22 -4
  159. package/dist/embedded-transaction.d.ts.map +1 -1
  160. package/dist/embedded-transaction.js +51 -5
  161. package/dist/feltdb.d.ts +14 -2
  162. package/dist/feltdb.d.ts.map +1 -1
  163. package/dist/file-db.js +1 -1
  164. package/dist/http-client.d.ts +14 -0
  165. package/dist/http-client.d.ts.map +1 -1
  166. package/dist/http-client.js +23 -5
  167. package/dist/http-db.d.ts +119 -1
  168. package/dist/http-db.d.ts.map +1 -1
  169. package/dist/http-db.js +346 -31
  170. package/dist/index-core.d.ts +2 -0
  171. package/dist/index-core.d.ts.map +1 -1
  172. package/dist/index-core.js +2 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +9 -0
  175. package/dist/indexeddb-db.d.ts.map +1 -1
  176. package/dist/indexeddb-db.js +35 -21
  177. package/dist/managed-recovery.d.ts +192 -0
  178. package/dist/managed-recovery.d.ts.map +1 -0
  179. package/dist/managed-recovery.js +242 -0
  180. package/dist/memory-db.js +1 -1
  181. package/dist/studio-app/assets/{feltdb_wasm-DB8cX151.js → feltdb_wasm-DaNwCLRX.js} +1 -1
  182. package/dist/studio-app/assets/feltdb_wasm_bg-DnsHNv6g.wasm +0 -0
  183. package/dist/studio-app/assets/index-j8IlhNqJ.js +29 -0
  184. package/dist/studio-app/index.html +1 -1
  185. package/dist/transaction.d.ts +30 -0
  186. package/dist/transaction.d.ts.map +1 -1
  187. package/dist/transaction.js +41 -0
  188. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  189. package/dist/workload.d.ts +2 -1
  190. package/dist/workload.d.ts.map +1 -1
  191. package/package.json +1 -1
  192. package/dist/studio-app/assets/feltdb_wasm_bg-ClhDHp0S.wasm +0 -0
  193. package/dist/studio-app/assets/index-B0k4UAlI.js +0 -29
@@ -0,0 +1,234 @@
1
+ //! PR34 — bounded query execution without collection materialization.
2
+ //!
3
+ //! `FeltDb::query_collection` is the state-access primitive the bounded query
4
+ //! surface executes on. These tests pin the two properties the query path
5
+ //! depends on: it observes every live record of a collection in record-key
6
+ //! order, and it clones only the records its predicate retains.
7
+
8
+ use feltdb::{query_execution_diagnostics, FeltDb, StoredRow};
9
+ use serde_json::json;
10
+ use std::sync::{Mutex, MutexGuard, OnceLock};
11
+ use tempfile::TempDir;
12
+
13
+ /// The read counters are process-global, and the test binary runs its tests in
14
+ /// threads of one process, so a counter assertion is only meaningful while no
15
+ /// other test in this file is reading a collection.
16
+ fn exclusive() -> MutexGuard<'static, ()> {
17
+ static SERIAL: OnceLock<Mutex<()>> = OnceLock::new();
18
+ SERIAL
19
+ .get_or_init(|| Mutex::new(()))
20
+ .lock()
21
+ .unwrap_or_else(|poisoned| poisoned.into_inner())
22
+ }
23
+
24
+ fn seeded(records: usize) -> (TempDir, FeltDb) {
25
+ let directory = TempDir::new().expect("temp dir");
26
+ let db = FeltDb::open(directory.path().join("pr34.log")).expect("open db");
27
+ for index in 0..records {
28
+ db.insert(
29
+ &format!("items:record-{index:05}"),
30
+ json!({ "tenant": format!("tenant-{}", index % 4), "n": index }),
31
+ )
32
+ .expect("insert");
33
+ }
34
+ (directory, db)
35
+ }
36
+
37
+ #[test]
38
+ fn scan_returns_only_matching_records() {
39
+ let _serial = exclusive();
40
+ let (_directory, db) = seeded(40);
41
+
42
+ let matches = db
43
+ .query_collection("items", None, |row| {
44
+ row.value.get("tenant") == Some(&json!("tenant-1"))
45
+ })
46
+ .expect("scan");
47
+
48
+ assert_eq!(matches.len(), 10, "one quarter of the collection matches");
49
+ assert!(matches
50
+ .iter()
51
+ .all(|row| row.value.get("tenant") == Some(&json!("tenant-1"))));
52
+ }
53
+
54
+ #[test]
55
+ fn scan_of_an_empty_or_unknown_collection_is_empty() {
56
+ let _serial = exclusive();
57
+ let (_directory, db) = seeded(0);
58
+
59
+ assert!(db
60
+ .query_collection("items", None, |_| true)
61
+ .expect("scan")
62
+ .is_empty());
63
+ assert!(db
64
+ .query_collection("no-such-collection", None, |_| true)
65
+ .expect("scan")
66
+ .is_empty());
67
+ }
68
+
69
+ #[test]
70
+ fn scan_visits_records_in_record_key_order() {
71
+ let _serial = exclusive();
72
+ let (_directory, db) = seeded(16);
73
+
74
+ let keys: Vec<String> = db
75
+ .query_collection("items", None, |_| true)
76
+ .expect("scan")
77
+ .iter()
78
+ .map(|row: &StoredRow| row.key.clone())
79
+ .collect();
80
+ let mut sorted = keys.clone();
81
+ sorted.sort();
82
+
83
+ assert_eq!(keys, sorted, "traversal follows the collection's key order");
84
+ }
85
+
86
+ #[test]
87
+ fn a_limit_stops_the_traversal_once_it_is_satisfied() {
88
+ let _serial = exclusive();
89
+ let (_directory, db) = seeded(500);
90
+
91
+ let mut visited = 0usize;
92
+ let matches = db
93
+ .query_collection("items", Some(5), |_| {
94
+ visited += 1;
95
+ true
96
+ })
97
+ .expect("scan");
98
+
99
+ assert_eq!(matches.len(), 5, "the limit bounds the result");
100
+ assert_eq!(
101
+ visited, 5,
102
+ "a satisfied limit stops the traversal instead of walking the collection"
103
+ );
104
+ }
105
+
106
+ #[test]
107
+ fn a_scan_clones_only_the_records_it_retains() {
108
+ let _serial = exclusive();
109
+ let (_directory, db) = seeded(2_000);
110
+
111
+ let before = query_execution_diagnostics::counters();
112
+ let matches = db
113
+ .query_collection("items", None, |row| row.value.get("n") == Some(&json!(7)))
114
+ .expect("scan");
115
+ let after = query_execution_diagnostics::counters();
116
+
117
+ assert_eq!(matches.len(), 1);
118
+ assert_eq!(
119
+ after.full_collection_materializations, before.full_collection_materializations,
120
+ "a scan must not fall back to full collection materialization"
121
+ );
122
+ assert_eq!(
123
+ after.scan_records_visited - before.scan_records_visited,
124
+ 2_000,
125
+ "the predicate observes every record, borrowed"
126
+ );
127
+ assert_eq!(
128
+ after.scan_records_materialized - before.scan_records_materialized,
129
+ 1,
130
+ "only the matching record is cloned"
131
+ );
132
+ }
133
+
134
+ #[test]
135
+ fn full_materialization_is_still_counted_for_readers_that_ask_for_it() {
136
+ let _serial = exclusive();
137
+ let (_directory, db) = seeded(32);
138
+
139
+ let before = query_execution_diagnostics::counters();
140
+ let rows = db.list_collection("items").expect("list");
141
+ let after = query_execution_diagnostics::counters();
142
+
143
+ assert_eq!(rows.len(), 32);
144
+ assert_eq!(
145
+ after.full_collection_materializations - before.full_collection_materializations,
146
+ 1
147
+ );
148
+ assert_eq!(
149
+ after.full_collection_records_cloned - before.full_collection_records_cloned,
150
+ 32,
151
+ "listing a collection clones every record in it"
152
+ );
153
+ }
154
+
155
+ #[test]
156
+ fn a_scan_result_survives_concurrent_mutation() {
157
+ let _serial = exclusive();
158
+ let (_directory, db) = seeded(200);
159
+
160
+ let matches = db
161
+ .query_collection("items", None, |row| {
162
+ row.value.get("tenant") == Some(&json!("tenant-0"))
163
+ })
164
+ .expect("scan");
165
+
166
+ // The scan returns owned records, so mutation after the lock is released
167
+ // cannot invalidate or rewrite what the caller already holds.
168
+ for index in 0..200 {
169
+ db.delete(&format!("items:record-{index:05}"))
170
+ .expect("delete");
171
+ }
172
+
173
+ assert_eq!(matches.len(), 50);
174
+ assert!(matches
175
+ .iter()
176
+ .all(|row| row.value.get("tenant") == Some(&json!("tenant-0"))));
177
+ assert!(db
178
+ .query_collection("items", None, |_| true)
179
+ .expect("scan")
180
+ .is_empty());
181
+ }
182
+
183
+ /// PR35 addition: the indexed execution must not reach the materializing path.
184
+ ///
185
+ /// PR34's claim was that a bounded query never enters `list_collection`. PR35
186
+ /// adds a second execution, and an optimization that quietly fell back into a
187
+ /// whole-collection clone would satisfy every correctness test in this
188
+ /// repository while undoing the thing PR34 established. So the property is
189
+ /// re-asserted against the execution that did not exist when it was first
190
+ /// proved: indexed execution materializes nothing, and does not scan either.
191
+ #[test]
192
+ fn an_indexed_query_neither_materializes_nor_scans_the_collection() {
193
+ let _serial = exclusive();
194
+ let (_directory, db) = seeded(400);
195
+ db.create_equality_index("items", "tenant")
196
+ .expect("declare index");
197
+
198
+ let before = query_execution_diagnostics::counters();
199
+ let tenant = json!("tenant-1");
200
+ let matches = db
201
+ .query_collection_by_equality("items", &[("tenant", &tenant)], |row| {
202
+ row.value.get("tenant") == Some(&json!("tenant-1"))
203
+ })
204
+ .expect("indexed query")
205
+ .expect("the field is indexed");
206
+ let after = query_execution_diagnostics::counters();
207
+
208
+ assert_eq!(matches.len(), 100, "one quarter of the collection matches");
209
+ assert_eq!(
210
+ after.full_collection_materializations - before.full_collection_materializations,
211
+ 0,
212
+ "indexed execution must not enter the full-collection materialization path",
213
+ );
214
+ assert_eq!(
215
+ after.collection_scans - before.collection_scans,
216
+ 0,
217
+ "indexed execution is not a scan",
218
+ );
219
+ assert_eq!(
220
+ after.scan_records_visited - before.scan_records_visited,
221
+ 0,
222
+ "and therefore visits no record by traversal",
223
+ );
224
+ assert_eq!(
225
+ after.queries_indexed - before.queries_indexed,
226
+ 1,
227
+ "the query is attributed to the indexed execution",
228
+ );
229
+ assert_eq!(
230
+ after.records_predicate_evaluated - before.records_predicate_evaluated,
231
+ 100,
232
+ "the predicate runs against the candidate set, not the collection",
233
+ );
234
+ }