(
&self,
collection: &str,
id: &str,
embedding: &[f32],
metadata: Option<Document>,
)
| 27 | } |
| 28 | |
| 29 | pub(super) async fn vector_insert_impl( |
| 30 | &self, |
| 31 | collection: &str, |
| 32 | id: &str, |
| 33 | embedding: &[f32], |
| 34 | metadata: Option<Document>, |
| 35 | ) -> NodeDbResult<()> { |
| 36 | // Serialize metadata up front. A serialization failure must |
| 37 | // propagate — the prior `unwrap_or_else(|_| "{}")` silently |
| 38 | // replaced caller-supplied metadata with an empty object, which |
| 39 | // is exactly the silent-drop pattern this client guards against |
| 40 | // on every other seam (filter bytes, bind params). |
| 41 | let meta_json = match metadata { |
| 42 | Some(d) => { |
| 43 | let obj: std::collections::HashMap<String, nodedb_types::value::Value> = d.fields; |
| 44 | sonic_rs::to_string(&obj).map_err(|e| { |
| 45 | NodeDbError::serialization("json", format!("vector_insert metadata: {e}")) |
| 46 | })? |
| 47 | } |
| 48 | None => "{}".to_string(), |
| 49 | }; |
| 50 | let sql = format!( |
| 51 | "INSERT INTO {} (id, embedding, metadata) VALUES ({}, {}, {})", |
| 52 | quote_identifier(collection), |
| 53 | quote_string_literal(id), |
| 54 | format_f32_array(embedding), |
| 55 | quote_string_literal(&meta_json), |
| 56 | ); |
| 57 | let mut conn = self.pool.acquire().await?; |
| 58 | conn.execute_sql(&sql).await?; |
| 59 | Ok(()) |
| 60 | } |
| 61 | |
| 62 | pub(super) async fn vector_delete_impl(&self, collection: &str, id: &str) -> NodeDbResult<()> { |
| 63 | let sql = format!( |
no test coverage detected