Skip to content

Commit 07d659a

Browse files
committed
fix: adapt to updated core crate APIs across query, graph, and storage
Bump nodedb-* workspace dependencies to 0.4 and follow through on their API changes: switch `PlanVisitor` methods to struct-style `*VisitArgs`, adopt `BfsParams`/`ShortestPathParams` for graph traversal, support computed GROUP BY keys via `GroupKeySpec` and MERGE source-expression values via `UpdateValue::Expr`, handle new `MetaOp` transaction-overlay and Calvin variants as unsupported on the single-node engine, propagate the new fallible HNSW checkpoint encoding, and update wire-version and formatting fallout in the affected tests.
1 parent 4e26e9f commit 07d659a

27 files changed

Lines changed: 573 additions & 317 deletions

File tree

Cargo.toml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ homepage = "https://nodedb.dev"
1414
[workspace.dependencies]
1515
# Internal
1616
nodedb-lite = { path = "nodedb-lite", version = "0.1.0", default-features = false }
17-
nodedb-types = { version = "0.3" }
18-
nodedb-client = { version = "0.3" }
19-
nodedb-codec = { version = "0.3" }
20-
nodedb-crdt = { version = "0.3" }
21-
nodedb-query = { version = "0.3" }
22-
nodedb-spatial = { version = "0.3" }
23-
nodedb-graph = { version = "0.3" }
24-
nodedb-vector = { version = "0.3" }
25-
nodedb-fts = { version = "0.3" }
26-
nodedb-strict = { version = "0.3" }
27-
nodedb-columnar = { version = "0.3" }
28-
nodedb-sql = { version = "0.3" }
29-
nodedb-array = { version = "0.3" }
30-
nodedb-physical = { version = "0.3" }
17+
nodedb-types = { version = "0.4" }
18+
nodedb-client = { version = "0.4" }
19+
nodedb-codec = { version = "0.4" }
20+
nodedb-crdt = { version = "0.4" }
21+
nodedb-query = { version = "0.4" }
22+
nodedb-spatial = { version = "0.4" }
23+
nodedb-graph = { version = "0.4" }
24+
nodedb-vector = { version = "0.4" }
25+
nodedb-fts = { version = "0.4" }
26+
nodedb-strict = { version = "0.4" }
27+
nodedb-columnar = { version = "0.4" }
28+
nodedb-sql = { version = "0.4" }
29+
nodedb-array = { version = "0.4" }
30+
nodedb-physical = { version = "0.4" }
3131

3232
# Async
3333
tokio = { version = "1" }

nodedb-lite/src/nodedb/batch.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,17 @@ impl<S: StorageEngine> NodeDbLite<S> {
176176
match indices.get(&name) {
177177
Some(idx) => {
178178
if seg_ext.is_some() {
179-
let graph_bytes = idx.graph_checkpoint_to_bytes();
179+
let graph_bytes = idx.graph_checkpoint_to_bytes().map_err(|e| {
180+
NodeDbError::serialization("hnsw-graph-checkpoint", e)
181+
})?;
180182
let (vectors, surrogates) = idx.extract_vectors_and_surrogates();
181183
let dim = idx.dim();
182184
(graph_bytes, Some((dim, vectors, surrogates)))
183185
} else {
184-
(idx.checkpoint_to_bytes(), None)
186+
let blob = idx
187+
.checkpoint_to_bytes()
188+
.map_err(|e| NodeDbError::serialization("hnsw-checkpoint", e))?;
189+
(blob, None)
185190
}
186191
}
187192
None => continue,
@@ -191,7 +196,9 @@ impl<S: StorageEngine> NodeDbLite<S> {
191196
let blob = {
192197
let indices = self.vector_state.hnsw_indices.lock_or_recover();
193198
match indices.get(&name) {
194-
Some(idx) => idx.checkpoint_to_bytes(),
199+
Some(idx) => idx
200+
.checkpoint_to_bytes()
201+
.map_err(|e| NodeDbError::serialization("hnsw-checkpoint", e))?,
195202
None => continue,
196203
}
197204
};

nodedb-lite/src/nodedb/core/flush.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ impl<S: StorageEngine> NodeDbLite<S> {
197197
{
198198
if seg_ext.is_some() {
199199
// Graph-only blob (vector bytes are empty placeholders).
200-
let graph_bytes = index.graph_checkpoint_to_bytes();
200+
let graph_bytes = index
201+
.graph_checkpoint_to_bytes()
202+
.map_err(|e| NodeDbError::serialization("hnsw-graph-checkpoint", e))?;
201203
ops.push(WriteOp::Put {
202204
ns: Namespace::Vector,
203205
key: key.into_bytes(),
@@ -209,7 +211,9 @@ impl<S: StorageEngine> NodeDbLite<S> {
209211
segment_data.push((name.clone(), dim, vectors, surrogates));
210212
} else {
211213
// Non-pagedb native backend: full checkpoint blob path.
212-
let checkpoint = index.checkpoint_to_bytes();
214+
let checkpoint = index
215+
.checkpoint_to_bytes()
216+
.map_err(|e| NodeDbError::serialization("hnsw-checkpoint", e))?;
213217
ops.push(WriteOp::Put {
214218
ns: Namespace::Vector,
215219
key: key.into_bytes(),

nodedb-lite/src/nodedb/trait_impl/graph.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,14 @@ impl<S: StorageEngine> NodeDbLite<S> {
401401
let csr_map = self.csr.lock_or_recover();
402402
let path = match csr_map.get(collection) {
403403
Some(csr) => csr.shortest_path(
404-
from.as_str(),
405-
to.as_str(),
406-
label_filter,
407-
max_depth as usize,
408-
DEFAULT_MAX_VISITED,
404+
nodedb_graph::ShortestPathParams {
405+
src: from.as_str(),
406+
dst: to.as_str(),
407+
label_filter,
408+
max_depth: max_depth as usize,
409+
max_visited: DEFAULT_MAX_VISITED,
410+
frontier_bitmap: None,
411+
},
409412
None,
410413
),
411414
None => None,

nodedb-lite/src/query/document_ops/sets.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ pub async fn merge<S: StorageEngine>(
366366
.get(source_join_col)
367367
.map(value_to_string)
368368
.unwrap_or_else(|| key.clone());
369-
let map: HashMap<String, Value> = build_insert_map(columns, values)?;
369+
let map: HashMap<String, Value> = build_insert_map(columns, values, source_val)?;
370370
let bytes = zerompk::to_msgpack_vec(&Value::Object(map)).map_err(|e| {
371371
LiteError::Serialization {
372372
detail: format!("merge insert serialize: {e}"),
@@ -525,18 +525,31 @@ fn qualify_updates_with_source(
525525
Ok(updates.to_vec())
526526
}
527527

528-
/// Decode a parallel (columns, values) pair into a field map.
529-
fn build_insert_map(
528+
/// Resolve a parallel (columns, values) pair into a field map, evaluating each
529+
/// value against the source row.
530+
///
531+
/// `UpdateValue::Literal` arms decode the pre-encoded msgpack directly.
532+
/// `UpdateValue::Expr` arms (e.g. `s.new_embedding`, `s.qty * 2`) are evaluated
533+
/// against the source row — Lite's `convert_sql_expr` strips table qualifiers,
534+
/// so column references resolve against the source row's bare field names. The
535+
/// result is stored under the *target* column name.
536+
pub(in crate::query) fn build_insert_map(
530537
columns: &[String],
531-
values: &[Vec<u8>],
538+
values: &[UpdateValue],
539+
source_val: &HashMap<String, Value>,
532540
) -> Result<HashMap<String, Value>, LiteError> {
541+
let source_ndb = Value::Object(source_val.clone());
533542
let mut map = HashMap::with_capacity(columns.len());
534-
for (col, val_bytes) in columns.iter().zip(values.iter()) {
535-
let val: Value =
536-
zerompk::from_msgpack(val_bytes).map_err(|e| LiteError::Serialization {
537-
detail: format!("merge insert decode column '{col}': {e}"),
538-
})?;
539-
map.insert(col.clone(), val);
543+
for (col, val) in columns.iter().zip(values.iter()) {
544+
let resolved: Value = match val {
545+
UpdateValue::Literal(bytes) => {
546+
zerompk::from_msgpack(bytes).map_err(|e| LiteError::Serialization {
547+
detail: format!("merge insert decode column '{col}': {e}"),
548+
})?
549+
}
550+
UpdateValue::Expr(expr) => expr.eval(&source_ndb),
551+
};
552+
map.insert(col.clone(), resolved);
540553
}
541554
Ok(map)
542555
}
@@ -560,7 +573,7 @@ async fn apply_merge_action<S: StorageEngine>(
560573
point_delete(engine, collection, doc_id).await?;
561574
}
562575
MergeActionOp::Insert { columns, values } => {
563-
let map = build_insert_map(columns, values)?;
576+
let map = build_insert_map(columns, values, source_val)?;
564577
let bytes = zerompk::to_msgpack_vec(&Value::Object(map)).map_err(|e| {
565578
LiteError::Serialization {
566579
detail: format!("merge action insert serialize: {e}"),

nodedb-lite/src/query/graph_ops/fusion.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,14 @@ pub async fn rag_fusion<S: StorageEngine>(
141141
.saturating_mul(vector_top_k)
142142
.max(DEFAULT_MAX_VISITED);
143143
let expanded = csr.traverse_bfs(
144-
&starts,
145-
edge_label,
146-
direction,
147-
expansion_depth,
148-
max_vis,
144+
nodedb_graph::BfsParams {
145+
start_nodes: &starts,
146+
label_filter: edge_label,
147+
direction,
148+
max_depth: expansion_depth,
149+
max_visited: max_vis,
150+
frontier_bitmap: None,
151+
},
149152
None,
150153
);
151154

@@ -302,6 +305,7 @@ mod tests {
302305
vector_state,
303306
array_state,
304307
fts_state,
308+
Arc::new(crate::engine::sparse_vector::SparseVectorState::new()),
305309
spatial,
306310
Arc::new(Mutex::new(std::collections::HashMap::new())),
307311
)

nodedb-lite/src/query/graph_ops/match_engine/executor.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,15 @@ fn execute_triple(
139139
if triple.edge.is_variable_length() {
140140
for src_name in &src_nodes {
141141
let expanded = csr.traverse_bfs(
142-
&[src_name.as_str()],
143-
label_filter,
144-
direction,
145-
triple.edge.max_hops,
146-
50_000,
147-
frontier_bitmap,
142+
nodedb_graph::BfsParams {
143+
start_nodes: &[src_name.as_str()],
144+
label_filter,
145+
direction,
146+
max_depth: triple.edge.max_hops,
147+
max_visited: 50_000,
148+
frontier_bitmap,
149+
},
150+
None,
148151
);
149152
for dst_name in expanded {
150153
if dst_name == *src_name && triple.edge.min_hops > 0 {

nodedb-lite/src/query/graph_ops/traversal.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,17 @@ pub fn hop(
5050

5151
let starts: Vec<&str> = start_nodes.iter().map(String::as_str).collect();
5252
let mv = max_visited(options);
53-
let nodes = csr.traverse_bfs(&starts, edge_label, direction, depth, mv, frontier_bitmap);
53+
let nodes = csr.traverse_bfs(
54+
nodedb_graph::BfsParams {
55+
start_nodes: &starts,
56+
label_filter: edge_label,
57+
direction,
58+
max_depth: depth,
59+
max_visited: mv,
60+
frontier_bitmap,
61+
},
62+
None,
63+
);
5464

5565
let rows = nodes.iter().map(|n| node_row(n)).collect();
5666
Ok(QueryResult {
@@ -155,7 +165,17 @@ pub fn path(
155165
};
156166

157167
let mv = max_visited(options);
158-
let maybe_path = csr.shortest_path(src, dst, edge_label, max_depth, mv, frontier_bitmap);
168+
let maybe_path = csr.shortest_path(
169+
nodedb_graph::ShortestPathParams {
170+
src,
171+
dst,
172+
label_filter: edge_label,
173+
max_depth,
174+
max_visited: mv,
175+
frontier_bitmap,
176+
},
177+
None,
178+
);
159179

160180
let columns = vec!["path".to_string()];
161181
let rows = match maybe_path {
@@ -189,7 +209,7 @@ pub fn subgraph(
189209

190210
let starts: Vec<&str> = start_nodes.iter().map(String::as_str).collect();
191211
let mv = max_visited(options);
192-
let edges = csr.subgraph(&starts, edge_label, depth, mv);
212+
let edges = csr.subgraph(&starts, edge_label, Direction::Out, depth, mv, None);
193213

194214
let columns = vec!["src".to_string(), "label".to_string(), "dst".to_string()];
195215
let rows = edges

nodedb-lite/src/query/meta_ops/temporal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ mod tests {
196196
vector_state,
197197
array_state,
198198
fts_state,
199+
Arc::new(crate::engine::sparse_vector::SparseVectorState::new()),
199200
spatial,
200201
Arc::new(Mutex::new(std::collections::HashMap::new())),
201202
)

nodedb-lite/src/query/physical_visitor/adapter/kv.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
167167
collection,
168168
entries,
169169
ttl_ms,
170+
surrogates: _,
170171
} => {
171172
let col = collection.clone();
172173
let ents = entries.clone();
@@ -209,6 +210,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
209210
key,
210211
delta,
211212
ttl_ms,
213+
surrogate: _,
212214
} => {
213215
let col = collection.clone();
214216
let k = key.clone();
@@ -223,6 +225,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
223225
collection,
224226
key,
225227
delta,
228+
surrogate: _,
226229
} => {
227230
let col = collection.clone();
228231
let k = key.clone();
@@ -237,6 +240,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
237240
key,
238241
expected,
239242
new_value,
243+
surrogate: _,
240244
} => {
241245
let col = collection.clone();
242246
let k = key.clone();
@@ -251,6 +255,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
251255
collection,
252256
key,
253257
new_value,
258+
surrogate: _,
254259
} => {
255260
let col = collection.clone();
256261
let k = key.clone();
@@ -264,6 +269,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
264269
collection,
265270
key,
266271
updates,
272+
surrogate: _,
267273
} => {
268274
let col = collection.clone();
269275
let k = key.clone();
@@ -279,6 +285,8 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
279285
dest_key,
280286
field,
281287
amount,
288+
debit_surrogate: _,
289+
credit_surrogate: _,
282290
} => {
283291
let col = collection.clone();
284292
let src = source_key.clone();
@@ -295,6 +303,7 @@ pub(super) fn dispatch<'a, S: StorageEngine + 'a>(
295303
dest_collection,
296304
item_key,
297305
dest_key,
306+
surrogate: _,
298307
} => {
299308
let src_col = source_collection.clone();
300309
let dst_col = dest_collection.clone();

0 commit comments

Comments
 (0)