#![cfg(feature = "postgres-tests")]
use ferro_ai::pgvector::PgVectorStore;
use sqlx::PgPool;
async fn fresh_pg_pool() -> Option<PgPool> {
let url = std::env::var("DATABASE_URL").ok()?;
let pool = PgPool::connect(&url).await.expect("connect to postgres");
Some(pool)
}
#[tokio::test]
async fn store_and_nearest_roundtrip() {
if std::env::var("DATABASE_URL").is_err() {
eprintln!("DATABASE_URL not set — skipping pgvector integration test");
return;
}
let pool = fresh_pg_pool().await.expect("DATABASE_URL checked above");
sqlx::query("CREATE EXTENSION IF NOT EXISTS vector")
.execute(&pool)
.await
.expect("create extension vector");
let table = "ferro_ai_test_embeddings";
sqlx::query(&format!(
"CREATE TABLE IF NOT EXISTS {table} (id BIGINT PRIMARY KEY, vec vector(3))"
))
.execute(&pool)
.await
.expect("create test table");
sqlx::query(&format!("TRUNCATE {table}"))
.execute(&pool)
.await
.expect("truncate test table");
let store = PgVectorStore::new(table, "vec");
store
.store(&pool, 1, &[1.0_f32, 0.0, 0.0])
.await
.expect("store id=1");
store
.store(&pool, 2, &[0.0_f32, 1.0, 0.0])
.await
.expect("store id=2");
let neighbors = store
.nearest(&pool, &[0.9_f32, 0.1, 0.0], 2)
.await
.expect("nearest query");
assert_eq!(neighbors.len(), 2, "expected 2 neighbors");
assert_eq!(neighbors[0].id, 1, "nearest neighbor should be id=1");
let top_score = neighbors[0].score;
let second_score = neighbors[1].score;
assert!(
(-1.0..=1.0).contains(&top_score),
"score must be in [-1, 1], got {top_score}"
);
assert!(
top_score > second_score,
"id=1 score ({top_score}) should exceed id=2 score ({second_score})"
);
sqlx::query(&format!("DROP TABLE IF EXISTS {table}"))
.execute(&pool)
.await
.expect("drop test table");
}