1pub mod engine;
33pub mod error;
34pub mod types;
35
36#[doc(hidden)]
39pub(crate) mod degree_cache;
40#[doc(hidden)]
41pub(crate) mod dense_hnsw;
42#[doc(hidden)]
43pub(crate) mod edge_metadata;
44#[doc(hidden)]
45pub(crate) mod encoding;
46#[doc(hidden)]
47pub(crate) mod gql;
48#[doc(hidden)]
49pub(crate) mod graph_row;
50#[doc(hidden)]
53pub mod manifest;
54#[doc(hidden)]
55pub(crate) mod memtable;
56#[doc(hidden)]
57pub(crate) mod parallel;
58#[doc(hidden)]
59pub(crate) mod planner_stats;
60#[doc(hidden)]
61pub(crate) mod property_value_semantics;
62#[doc(hidden)]
63pub(crate) mod row_projection;
64#[doc(hidden)]
65pub(crate) mod scrub;
66#[doc(hidden)]
67pub(crate) mod segment_components;
68#[doc(hidden)]
69pub(crate) mod segment_reader;
70#[doc(hidden)]
71pub(crate) mod segment_writer;
72#[doc(hidden)]
73pub(crate) mod source_list;
74#[doc(hidden)]
75pub(crate) mod sparse_postings;
76#[doc(hidden)]
77pub(crate) mod wal;
78#[doc(hidden)]
79pub(crate) mod wal_sync;
80
81pub use engine::{DatabaseEngine, WriteTxn};
82pub use error::EngineError;
83pub use types::{
84 canonicalize_sparse_vector, canonicalize_sparse_vector_owned, hash_prop_key, hash_prop_value,
85 validate_dense_vector, validate_dense_vector_config, AdjacencyExport, AllShortestPathsOptions,
86 CompactionPhase, CompactionProgress, CompactionStats, ComponentOptions, ComponentScrubFinding,
87 DbOptions, DbStats, DegreeOptions, DenseMetric, DenseVector, DenseVectorConfig, Direction,
88 EdgeFilterExpr, EdgeInput, EdgeLabelInfo, EdgePropertyIndexInfo, EdgeQuery, EdgeQueryOrder,
89 EdgeView, ExportEdge, ExportOptions, FusionMode, GqlCapSummary, GqlEdge,
90 GqlExecutionCapSummary, GqlExecutionExplain, GqlExecutionMode, GqlExecutionOptions,
91 GqlExecutionResult, GqlExecutionStats, GqlExplain, GqlLoweringTarget, GqlMutationExplain,
92 GqlMutationOperationExplain, GqlMutationReadPrefixExplain, GqlMutationReturnExplain,
93 GqlMutationStats, GqlNode, GqlParamValue, GqlParams, GqlRow, GqlRowOperation,
94 GqlSemanticErrorCode, GqlStatementKind, GqlValue, GraphBinaryOp, GraphCapExplain,
95 GraphCaseBranch, GraphCursorExplain, GraphEdgeField, GraphEdgePattern, GraphEdgeValue,
96 GraphElementProjection, GraphExecutionSummaries, GraphExplainNode, GraphExpr, GraphFunction,
97 GraphNodeField, GraphNodePattern, GraphNodeValue, GraphOptionalGroup, GraphOrderDirection,
98 GraphOrderExplain, GraphOrderItem, GraphOutputMode, GraphOutputOptions, GraphPageRequest,
99 GraphParamValue, GraphPatch, GraphPath, GraphPathField, GraphPathValue, GraphPatternPiece,
100 GraphPipelineCapExplain, GraphPipelineExplain, GraphPipelineMatchStage, GraphPipelineOptions,
101 GraphPipelineQuery, GraphPipelineResult, GraphPipelineStage, GraphPipelineStageExplain,
102 GraphPipelineStats, GraphProjectItem, GraphProjectKind, GraphProjectStage,
103 GraphProjectionExplain, GraphProjectionItems, GraphPropertySelection, GraphQueryOptions,
104 GraphReturnItem, GraphReturnProjection, GraphRow, GraphRowExplain, GraphRowOperationExplain,
105 GraphRowQuery, GraphRowResult, GraphRowStats, GraphSelectedEdgeProjection,
106 GraphSelectedNodeProjection, GraphSelectedPathProjection, GraphSelectedProjection,
107 GraphShortestPathEndpoint, GraphShortestPathMode, GraphShortestPathStage, GraphSubqueryStage,
108 GraphUnaryOp, GraphUnionStage, GraphValue, GraphVariableLengthPattern, GraphVectorSelection,
109 HnswConfig, IntoNodeLabels, IsConnectedOptions, LabelMatchMode, ManifestState, NeighborEntry,
110 NeighborOptions, NodeFilterExpr, NodeIdBuildHasher, NodeIdHasher, NodeIdMap, NodeIdSet,
111 NodeInput, NodeKeyQuery, NodeLabelFilter, NodeLabelInfo, NodePropertyIndexInfo, NodeQuery,
112 NodeQueryOrder, NodeView, PageRequest, PageResult, PatchResult, PprAlgorithm, PprApproxMeta,
113 PprOptions, PprResult, PropValue, PropertyRangeBound, PropertyRangeCursor,
114 PropertyRangePageRequest, PropertyRangePageResult, PrunePolicy, PrunePolicyInfo, PruneResult,
115 QueryEdgeIdsResult, QueryEdgesResult, QueryNodeIdsResult, QueryNodesResult, QueryPlan,
116 QueryPlanKind, QueryPlanNode, QueryPlanNote, QueryPlanPublicInputs, QueryPlanPublicName,
117 QueryPlanWarning, ScoringMode, ScrubFindingType, ScrubReport, SecondaryIndexKind,
118 SecondaryIndexManifestEntry, SecondaryIndexState, SecondaryIndexTarget, SegmentInfo,
119 SegmentScrubResult, ShortestPath, ShortestPathOptions, SourceSpan, SparseVector, Subgraph,
120 SubgraphOptions, TombstoneEntry, TopKOptions, TraversalCursor, TraversalHit,
121 TraversalPageResult, TraverseOptions, TxnCommitResult, TxnEdgeRef, TxnEdgeView, TxnIntent,
122 TxnLocalRef, TxnNodeRef, TxnNodeView, UpsertEdgeOptions, UpsertNodeOptions, VectorHit,
123 VectorSearchMode, VectorSearchRequest, VectorSearchScope, WalSyncMode, DEFAULT_DENSE_EF_SEARCH,
124};
125
126#[doc(hidden)]
127pub fn gql_referenced_param_names(
128 query: &str,
129 options: &GqlExecutionOptions,
130) -> Result<Vec<String>, EngineError> {
131 crate::gql::params::referenced_param_names_for_query(query, options)
132}
133
134#[cfg(test)]
135mod public_api_boundary_tests {
136 fn source(path: &str) -> String {
137 std::fs::read_to_string(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join(path))
138 .unwrap()
139 }
140
141 fn rust_source_paths() -> Vec<std::path::PathBuf> {
142 fn collect(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
143 for entry in std::fs::read_dir(dir).unwrap() {
144 let path = entry.unwrap().path();
145 if path.is_dir() {
146 collect(&path, out);
147 } else if path.extension().is_some_and(|ext| ext == "rs") {
148 out.push(path);
149 }
150 }
151 }
152
153 let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
154 let mut paths = Vec::new();
155 for dir in ["src", "tests", "benches"] {
156 collect(&root.join(dir), &mut paths);
157 }
158 paths
159 }
160
161 fn assert_files_do_not_contain(paths: &[std::path::PathBuf], patterns: &[String]) {
162 let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
163 for path in paths {
164 let contents = std::fs::read_to_string(path).unwrap();
165 let display = path.strip_prefix(root).unwrap_or(path).display();
166 for pattern in patterns {
167 assert!(
168 !contents.contains(pattern),
169 "`{pattern}` must not remain in Rust active edge-label source ({display})"
170 );
171 }
172 }
173 }
174
175 #[test]
176 fn internal_numeric_records_are_not_publicly_exported() {
177 let lib = source("src/lib.rs");
178 let types = source("src/types.rs");
179
180 assert!(
181 !lib.contains(concat!("pub use types", "::*")),
182 "public API must explicitly re-export stable DTOs and not glob-export internal records"
183 );
184 for forbidden in [
185 concat!("pub struct ", "NodeRecord"),
186 concat!("pub struct ", "EdgeRecord"),
187 ] {
188 assert!(
189 !types.contains(forbidden),
190 "`{forbidden}` would expose internal numeric label/type records"
191 );
192 }
193 for required in [
194 concat!("pub(crate) struct ", "NodeRecord"),
195 concat!("pub(crate) struct ", "EdgeRecord"),
196 ] {
197 assert!(
198 types.contains(required),
199 "`{required}` must remain the internal storage/WAL record boundary"
200 );
201 }
202 }
203
204 #[test]
205 fn graph_row_replacement_names_do_not_use_v2_suffixes() {
206 let paths = rust_source_paths();
207 assert_files_do_not_contain(
208 &paths,
209 &[
210 concat!("GraphRow", "V2").to_string(),
211 concat!("GraphRowQuery", "V2").to_string(),
212 concat!("GraphPatternPiece", "V2").to_string(),
213 concat!("GraphNodePattern", "V2").to_string(),
214 concat!("GraphEdgePattern", "V2").to_string(),
215 concat!("GraphReturnItem", "V2").to_string(),
216 concat!("GraphOutputOptions", "V2").to_string(),
217 concat!("GraphQueryOptions", "V2").to_string(),
218 concat!("GraphRowResult", "V2").to_string(),
219 concat!("GraphRowExplain", "V2").to_string(),
220 concat!("NormalizedGraphRowQuery", "V2").to_string(),
221 ],
222 );
223 }
224
225 #[test]
226 fn old_graph_pattern_public_exports_are_removed() {
227 let lib = source("src/lib.rs");
228 let types = source("src/types.rs");
229
230 for forbidden in [
231 concat!("Graph", "Pattern", "Query"),
232 concat!("Pattern", "Order"),
233 concat!("Query", "Match"),
234 concat!("Query", "Pattern", "Result"),
235 ] {
236 assert!(
237 !lib.contains(forbidden),
238 "`{forbidden}` must not be re-exported from the Rust public API"
239 );
240 }
241
242 for forbidden in [
243 concat!("pub struct ", "Graph", "Pattern", "Query"),
244 concat!("pub struct ", "Node", "Pattern"),
245 concat!("pub struct ", "Edge", "Pattern"),
246 concat!("pub enum ", "Pattern", "Order"),
247 concat!("pub struct ", "Query", "Pattern", "Result"),
248 concat!("pub struct ", "Query", "Match"),
249 concat!("Pattern", "Query"),
250 concat!("Pattern", "Expand"),
251 concat!("Pattern", "Edge", "Anchor"),
252 concat!("Unbounded", "Pattern", "Rejected"),
253 ] {
254 assert!(
255 !types.contains(forbidden),
256 "`{forbidden}` must not remain as a public/core graph-pattern DTO"
257 );
258 }
259 }
260
261 #[test]
262 fn old_graph_pattern_engine_methods_are_removed() {
263 let engine_query = source("src/engine/query.rs");
264 for forbidden in [
265 concat!("pub fn ", "query", "_pattern"),
266 concat!("pub fn ", "explain", "_pattern", "_query"),
267 ] {
268 assert!(
269 !engine_query.contains(forbidden),
270 "`{forbidden}` must not remain on DatabaseEngine"
271 );
272 }
273
274 for path in [
275 "src/engine/query_ir.rs",
276 "src/engine/query_exec.rs",
277 "src/engine/query_plan.rs",
278 "src/engine/projection.rs",
279 ] {
280 let contents = source(path);
281 for forbidden in [
282 concat!("Graph", "Pattern", "Query"),
283 concat!("Pattern", "Order"),
284 concat!("Query", "Match"),
285 concat!("Query", "Pattern", "Result"),
286 concat!("Normalized", "Graph", "Pattern", "Query"),
287 concat!("Planned", "Pattern", "Query"),
288 concat!("Pattern", "Plan", "Cost"),
289 concat!("Pattern", "Query"),
290 concat!("Pattern", "Expand"),
291 concat!("Pattern", "Edge", "Anchor"),
292 concat!("Unbounded", "Pattern", "Rejected"),
293 concat!("project", "_pattern", "_rows"),
294 ] {
295 assert!(
296 !contents.contains(forbidden),
297 "`{forbidden}` must not remain in old graph-pattern core path ({path})"
298 );
299 }
300 }
301 }
302
303 #[test]
304 fn rust_active_edge_label_id_vocabulary_has_no_backend_type_terms() {
305 let paths = rust_source_paths();
306 assert_files_do_not_contain(
307 &paths,
308 &[
309 concat!("EDGE", "_TYPE").to_string(),
310 concat!("Edge", "Type").to_string(),
311 concat!("edge", "_type").to_string(),
312 concat!("edge ", "type").to_string(),
313 concat!("edge", "-", "type").to_string(),
314 concat!("edges_by", "_type").to_string(),
315 concat!("visible_edges_by", "_type").to_string(),
316 concat!("type", "_edge_index").to_string(),
317 concat!("type", "_ids").to_string(),
318 concat!("type", "Id").to_string(),
319 concat!("type", " IDs").to_string(),
320 concat!("distinct ", "type").to_string(),
321 concat!("these ", "types").to_string(),
322 concat!("filtered", "_types").to_string(),
323 concat!("filtered", "_type", "_labels").to_string(),
324 concat!("Type ", "filter works").to_string(),
325 concat!("let ", "typed").to_string(),
326 concat!(":", "type", ":").to_string(),
327 concat!(":", "types", ":{").to_string(),
328 ],
329 );
330
331 let segment_reader = source("src/segment_reader.rs");
332 for pattern in [
333 concat!("entry", "_type"),
334 concat!("let e", "_type"),
335 concat!("match e", "_type"),
336 ] {
337 assert!(
338 !segment_reader.contains(pattern),
339 "`{pattern}` must not remain in segment edge label readers"
340 );
341 }
342 }
343
344 #[test]
345 fn implementation_modules_are_not_public_api() {
346 let lib = source("src/lib.rs");
347 for forbidden in [
348 concat!("pub mod ", "dense_hnsw;"),
349 concat!("pub mod ", "encoding;"),
350 concat!("pub mod ", "memtable;"),
351 concat!("pub mod ", "segment_reader;"),
352 concat!("pub mod ", "segment_writer;"),
353 concat!("pub mod ", "source_list;"),
354 concat!("pub mod ", "sparse_postings;"),
355 concat!("pub mod ", "wal;"),
356 concat!("pub mod ", "wal_sync;"),
357 ] {
358 assert!(
359 !lib.contains(forbidden),
360 "`{forbidden}` would expose implementation internals as Rust public API"
361 );
362 }
363 }
364
365 #[test]
366 fn manifest_module_public_surface_stays_read_only_diagnostic_only() {
367 let manifest = source("src/manifest.rs");
368 for forbidden in [
369 concat!("pub fn ", "write_manifest"),
370 concat!("pub fn ", "load_manifest("),
371 concat!("pub fn ", "default_manifest"),
372 ] {
373 assert!(
374 !manifest.contains(forbidden),
375 "`{forbidden}` must stay crate-private; manifest diagnostics expose read-only loading only"
376 );
377 }
378 assert!(
379 manifest.contains(concat!("pub fn ", "load_manifest_readonly")),
380 "the inspect binary relies on the explicit read-only diagnostic manifest loader"
381 );
382 }
383
384 #[test]
385 fn rust_public_edge_vocabulary_uses_labels() {
386 let lib = source("src/lib.rs");
387 let types = source("src/types.rs");
388 let engine = source("src/engine/mod.rs");
389 let read = source("src/engine/read.rs");
390 let write = source("src/engine/write.rs");
391 let txn = source("src/engine/txn.rs");
392 let manifest = source("src/manifest.rs");
393
394 for forbidden in [
395 concat!("Edge", "TypeInfo"),
396 concat!("pub edge", "_", "type:"),
397 concat!("pub edge", "_", "type", "_filter:"),
398 concat!("pub edge", "_", "type", "_index:"),
399 concat!("pub fn ensure_edge", "_", "type"),
400 concat!("pub fn get_edge", "_", "type("),
401 concat!("pub fn list_edge", "_", "types"),
402 concat!("pub fn ", "edges_by_label_id"),
403 concat!("pub fn ", "get_edges_by_label_id"),
404 concat!("pub fn ", "count_edges_by_label_id"),
405 ] {
406 assert!(
407 !lib.contains(forbidden)
408 && !types.contains(forbidden)
409 && !engine.contains(forbidden),
410 "`{forbidden}` must not remain in the Rust public edge-label API"
411 );
412 }
413
414 for forbidden in [
415 concat!("edge ", "type"),
416 concat!("edge", "-", "type"),
417 concat!("edge ", "type token"),
418 concat!("edge ", "type catalog"),
419 concat!("resolved by edge ", "type"),
420 concat!("transaction edge ", "type"),
421 ] {
422 assert!(
423 !types.contains(forbidden)
424 && !engine.contains(forbidden)
425 && !read.contains(forbidden)
426 && !write.contains(forbidden)
427 && !txn.contains(forbidden)
428 && !manifest.contains(forbidden),
429 "`{forbidden}` must not remain in public-facing Rust edge-label diagnostics or docs"
430 );
431 }
432
433 for required in [
434 "EdgeLabelInfo",
435 "pub label: String",
436 "pub edge_label_filter: Option<Vec<String>>",
437 "pub edge_label_index: u32",
438 "pub fn ensure_edge_label",
439 "pub fn get_edge_label_id",
440 "pub fn get_edge_label(",
441 "pub fn list_edge_labels",
442 "pub fn edges_by_label",
443 "pub fn get_edges_by_label",
444 "pub fn count_edges_by_label",
445 ] {
446 assert!(
447 lib.contains(required) || types.contains(required) || engine.contains(required),
448 "`{required}` should exist in the Rust public edge-label API"
449 );
450 }
451 }
452}