swiftide_integrations/pgvector/
persist.rs1use crate::pgvector::PgVector;
13use anyhow::{Result, anyhow};
14use async_trait::async_trait;
15use sqlx::AssertSqlSafe;
16use std::sync::Arc;
17use swiftide_core::{
18 Persist,
19 indexing::{IndexingStream, TextNode},
20};
21
22#[async_trait]
23impl Persist for PgVector {
24 type Input = String;
25 type Output = String;
26 #[tracing::instrument(skip_all)]
27 async fn setup(&self) -> Result<()> {
28 let pool = self.pool_get_or_initialize().await?;
30
31 if self.sql_stmt_bulk_insert.get().is_none() {
32 let sql = self.generate_unnest_upsert_sql()?;
33
34 self.sql_stmt_bulk_insert
35 .set(Arc::new(sql))
36 .map_err(|_| anyhow!("SQL bulk store statement is already set"))?;
37 }
38
39 let mut tx = pool.begin().await?;
40
41 let sql = "CREATE EXTENSION IF NOT EXISTS vector";
43 sqlx::query(sql).execute(&mut *tx).await?;
44
45 let create_table_sql = self.generate_create_table_sql()?;
47 sqlx::query(AssertSqlSafe(create_table_sql))
48 .execute(&mut *tx)
49 .await?;
50
51 let index_sql = self.create_index_sql()?;
53 sqlx::query(AssertSqlSafe(index_sql))
54 .execute(&mut *tx)
55 .await?;
56
57 tx.commit().await?;
58
59 Ok(())
60 }
61
62 #[tracing::instrument(skip_all)]
63 async fn store(&self, node: TextNode) -> Result<TextNode> {
64 let mut nodes = vec![node; 1];
65 self.store_nodes(&nodes).await?;
66
67 let node = nodes.swap_remove(0);
68
69 Ok(node)
70 }
71
72 #[tracing::instrument(skip_all)]
73 async fn batch_store(&self, nodes: Vec<TextNode>) -> IndexingStream<String> {
74 self.store_nodes(&nodes).await.map(|()| nodes).into()
75 }
76
77 fn batch_size(&self) -> Option<usize> {
78 Some(self.batch_size)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use crate::pgvector::fixtures::TestContext;
85 use std::collections::HashSet;
86 use swiftide_core::{Persist, indexing::EmbeddedField};
87
88 #[test_log::test(tokio::test)]
89 async fn test_persist_setup_no_error_when_table_exists() {
90 let test_context = TestContext::setup_with_cfg(
91 vec!["filter"].into(),
92 HashSet::from([EmbeddedField::Combined]),
93 )
94 .await
95 .expect("Test setup failed");
96
97 test_context
98 .pgv_storage
99 .setup()
100 .await
101 .expect("PgVector setup should not fail when the table already exists");
102 }
103}