diff --git a/cozo-core/src/parse/sys.rs b/cozo-core/src/parse/sys.rs index e997fcb6..4f3ad820 100644 --- a/cozo-core/src/parse/sys.rs +++ b/cozo-core/src/parse/sys.rs @@ -10,7 +10,7 @@ use std::collections::BTreeMap; use std::sync::Arc; use itertools::Itertools; -use miette::{ensure, miette, Diagnostic, Result}; +use miette::{ensure, miette, Diagnostic, Result, bail}; use smartstring::{LazyCompact, SmartString}; use thiserror::Error; @@ -254,6 +254,12 @@ pub(crate) fn parse_sys( _ => return Err(miette!("Invalid option: {}", opt_name.as_str())), } } + if ef_construction == 0 { + bail!("ef_construction must be set"); + } + if max_elements == 0 { + bail!("m_neighbours must be set"); + } SysOp::CreateVectorIndex(HnswIndexConfig { base_relation: SmartString::from(rel.as_str()), index_name: SmartString::from(name.as_str()), diff --git a/cozo-core/src/runtime/hnsw.rs b/cozo-core/src/runtime/hnsw.rs index 7b12f27a..ccb29578 100644 --- a/cozo-core/src/runtime/hnsw.rs +++ b/cozo-core/src/runtime/hnsw.rs @@ -178,7 +178,7 @@ impl<'a> SessionTx<'a> { self, &[], &[DataValue::from(i64::MIN)], - &[DataValue::from(1)], + &[DataValue::from(0)], ) .next(); if let Some(ep) = ep_res { @@ -802,6 +802,8 @@ impl<'a> SessionTx<'a> { .collect_vec(); encountered_singletons |= neigbours.is_empty(); for (neighbour_key, neighbour_idx, neighbour_subidx, _) in neigbours { + // REMARK: this still has some probability of disconnecting the graph. + // Should we accept that as a consequence of the probabilistic nature of the algorithm? let mut out_key = vec![DataValue::from(layer)]; out_key.extend_from_slice(tuple_key); out_key.push(DataValue::from(idx as i64)); diff --git a/cozo-core/src/runtime/relation.rs b/cozo-core/src/runtime/relation.rs index ffe19c83..91a7e045 100644 --- a/cozo-core/src/runtime/relation.rs +++ b/cozo-core/src/runtime/relation.rs @@ -737,7 +737,7 @@ impl<'a> SessionTx<'a> { for prefix in ["fr", "to"] { for col in rel_handle.metadata.keys.iter() { let mut col = col.clone(); - col.name = SmartString::from(format!("{}_{}", prefix, config.index_name)); + col.name = SmartString::from(format!("{}_{}", prefix, col.name)); idx_keys.push(col); } idx_keys.push(ColumnDef { diff --git a/cozo-core/src/runtime/tests.rs b/cozo-core/src/runtime/tests.rs index 6e771fe1..64e09914 100644 --- a/cozo-core/src/runtime/tests.rs +++ b/cozo-core/src/runtime/tests.rs @@ -849,3 +849,37 @@ fn test_vec_index() { println!("{} {} {}", row[0], row[1], row[2]); } } + +#[test] +fn test_insertions() { + let db = DbInstance::new("mem", "", "").unwrap(); + db.run_script( + r":create a {k => v: default rand_vec(100)}", + Default::default(), + ) + .unwrap(); + db.run_script(r"?[k] <- [[1]] :put a {k}", Default::default()) + .unwrap(); + db.run_script(r"?[k, v] := *a{k, v}", Default::default()) + .unwrap(); + db.run_script( + r"::hnsw create a:i {fields: [v], dim: 100, ef: 200, m: 50}", + Default::default(), + ) + .unwrap(); + db.run_script(r"?[count(fr_k)] := *a:i{fr_k}", Default::default()) + .unwrap(); + db.run_script(r"?[k] <- [[1]] :put a {k}", Default::default()) + .unwrap(); + db.run_script(r"?[k] := k in int_range(1000) :put a {k}", Default::default()).unwrap(); + let res = db + .run_script( + r"?[dist, k] := ~a:i{k | query: v, bind_distance: dist, k:10, ef: 200}, *a{k: 333, v}", + Default::default(), + ) + .unwrap(); + println!("results"); + for row in res.into_json()["rows"].as_array().unwrap() { + println!("{} {}", row[0], row[1]); + } +}