Skip to main content

klieo_memory_pgvector/
error.rs

1//! Error mapping from `sqlx` errors to [`klieo_core::error::MemoryError`].
2
3use klieo_core::error::MemoryError;
4use sqlx_core::error::Error as SqlxError;
5
6/// PostgreSQL SQLSTATE for `undefined_table` — raised when a query hits the
7/// facts table before the first `remember` has provisioned it.
8const UNDEFINED_TABLE: &str = "42P01";
9
10pub(crate) fn store_err(e: SqlxError) -> MemoryError {
11    MemoryError::Store(e.to_string())
12}
13
14/// Whether `e` is PostgreSQL's `undefined_table` (42P01). `recall` /
15/// `recall_filtered` map this to an empty result and `forget` to `Ok` — the
16/// table is created lazily on first `remember`, so a read that races ahead of
17/// any write sees "no facts", not a hard error (mirrors the Qdrant backend's
18/// missing-collection handling).
19pub(crate) fn is_undefined_table(e: &SqlxError) -> bool {
20    matches!(e, SqlxError::Database(db) if db.code().as_deref() == Some(UNDEFINED_TABLE))
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26
27    #[test]
28    fn store_err_routes_to_store_variant() {
29        let mem = store_err(SqlxError::PoolClosed);
30        assert!(matches!(mem, MemoryError::Store(_)));
31    }
32
33    #[test]
34    fn non_database_error_is_not_undefined_table() {
35        assert!(!is_undefined_table(&SqlxError::PoolClosed));
36    }
37}