use heliosdb_nano::{EmbeddedDatabase, Result};
#[test]
fn test_create_vector_index_sql() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE documents (
id INT4 PRIMARY KEY,
title TEXT,
embedding VECTOR(3)
)")?;
let result = db.execute("CREATE INDEX embedding_idx ON documents USING hnsw (embedding)");
assert!(result.is_ok(), "Failed to create HNSW index: {:?}", result.err());
Ok(())
}
#[test]
fn test_vector_distance_operators() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE vectors (id INT4, vec VECTOR(3))")?;
db.execute("INSERT INTO vectors (id, vec) VALUES (1, '[1.0, 0.0, 0.0]')")?;
db.execute("INSERT INTO vectors (id, vec) VALUES (2, '[0.0, 1.0, 0.0]')")?;
db.execute("INSERT INTO vectors (id, vec) VALUES (3, '[0.0, 0.0, 1.0]')")?;
Ok(())
}
#[test]
fn test_knn_query_pattern() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE embeddings (
id INT4,
text TEXT,
embedding VECTOR(3)
)")?;
db.execute("CREATE INDEX emb_idx ON embeddings USING hnsw (embedding)")?;
db.execute("INSERT INTO embeddings VALUES (1, 'apple', '[1.0, 0.0, 0.0]')")?;
db.execute("INSERT INTO embeddings VALUES (2, 'banana', '[0.9, 0.1, 0.0]')")?;
db.execute("INSERT INTO embeddings VALUES (3, 'cherry', '[0.0, 1.0, 0.0]')")?;
db.execute("INSERT INTO embeddings VALUES (4, 'date', '[0.0, 0.0, 1.0]')")?;
Ok(())
}
#[test]
fn test_vector_index_usage() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE large_vectors (
id INT4,
embedding VECTOR(128)
)")?;
db.execute("CREATE INDEX large_idx ON large_vectors USING hnsw (embedding)")?;
Ok(())
}
#[test]
fn test_distance_metrics() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE metric_test (id INT4, vec VECTOR(2))")?;
db.execute("INSERT INTO metric_test VALUES (1, '[1.0, 0.0]')")?;
db.execute("INSERT INTO metric_test VALUES (2, '[0.0, 1.0]')")?;
Ok(())
}
#[test]
fn test_create_index_if_not_exists() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE test_table (id INT4, vec VECTOR(3))")?;
db.execute("CREATE INDEX test_idx ON test_table USING hnsw (vec)")?;
let result = db.execute("CREATE INDEX IF NOT EXISTS test_idx ON test_table USING hnsw (vec)");
assert!(result.is_ok(), "IF NOT EXISTS should prevent error");
Ok(())
}
#[test]
fn test_vector_index_errors() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
let result = db.execute("CREATE INDEX bad_idx ON nonexistent USING hnsw (vec)");
assert!(result.is_err(), "Should fail on non-existent table");
db.execute("CREATE TABLE no_vector (id INT4, name TEXT)")?;
let result = db.execute("CREATE INDEX bad_idx ON no_vector USING hnsw (name)");
assert!(result.is_err(), "Should fail on non-vector column");
Ok(())
}
#[test]
fn test_vector_crud() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE vectors (id INT4, embedding VECTOR(3))")?;
db.execute("INSERT INTO vectors VALUES (1, '[1.0, 2.0, 3.0]')")?;
Ok(())
}
#[test]
fn test_full_vector_search_workflow() -> Result<()> {
let db = EmbeddedDatabase::new_in_memory()?;
db.execute("CREATE TABLE products (
id INT4 PRIMARY KEY,
name TEXT,
description TEXT,
embedding VECTOR(8)
)")?;
db.execute("CREATE INDEX product_emb_idx ON products USING hnsw (embedding)")?;
db.execute("INSERT INTO products VALUES (1, 'Laptop', 'Gaming laptop', '[1.0,0.8,0.2,0.1,0.3,0.5,0.7,0.9]')")?;
db.execute("INSERT INTO products VALUES (2, 'Mouse', 'Wireless mouse', '[1.0,0.7,0.3,0.2,0.4,0.6,0.8,0.1]')")?;
db.execute("INSERT INTO products VALUES (3, 'Keyboard', 'Mechanical keyboard', '[0.9,0.6,0.4,0.3,0.5,0.7,0.2,0.8]')")?;
db.execute("INSERT INTO products VALUES (4, 'Book', 'Programming book', '[0.1,0.2,0.3,0.9,0.8,0.7,0.6,0.5]')")?;
Ok(())
}