1use super::Store;
4use crate::error::MemoryError;
5use uuid::Uuid;
6
7impl Store {
8 pub async fn store_fact(
12 &self,
13 sender_id: &str,
14 key: &str,
15 value: &str,
16 ) -> Result<(), MemoryError> {
17 let id = Uuid::new_v4().to_string();
18 sqlx::query(
19 "INSERT INTO facts (id, sender_id, key, value) VALUES (?, ?, ?, ?) \
20 ON CONFLICT(sender_id, key) DO UPDATE SET \
21 value = excluded.value, \
22 updated_at = datetime('now'), \
23 deleted_at = NULL",
24 )
25 .bind(&id)
26 .bind(sender_id)
27 .bind(key)
28 .bind(value)
29 .execute(&self.pool)
30 .await
31 .map_err(|e| MemoryError::sqlite("upsert fact failed", e))?;
32
33 Ok(())
34 }
35
36 pub async fn get_fact(
39 &self,
40 sender_id: &str,
41 key: &str,
42 ) -> Result<Option<String>, MemoryError> {
43 let row: Option<(String,)> = sqlx::query_as(
44 "SELECT value FROM facts \
45 WHERE sender_id = ? AND key = ? AND deleted_at IS NULL",
46 )
47 .bind(sender_id)
48 .bind(key)
49 .fetch_optional(&self.pool)
50 .await
51 .map_err(|e| MemoryError::sqlite("query failed", e))?;
52
53 Ok(row.map(|(v,)| v))
54 }
55
56 pub async fn delete_fact(&self, sender_id: &str, key: &str) -> Result<bool, MemoryError> {
61 let result = sqlx::query("DELETE FROM facts WHERE sender_id = ? AND key = ?")
62 .bind(sender_id)
63 .bind(key)
64 .execute(&self.pool)
65 .await
66 .map_err(|e| MemoryError::sqlite("delete failed", e))?;
67
68 Ok(result.rows_affected() > 0)
69 }
70
71 pub async fn soft_delete_fact(&self, sender_id: &str, key: &str) -> Result<bool, MemoryError> {
74 let result = sqlx::query(
75 "UPDATE facts SET deleted_at = datetime('now') \
76 WHERE sender_id = ? AND key = ? AND deleted_at IS NULL",
77 )
78 .bind(sender_id)
79 .bind(key)
80 .execute(&self.pool)
81 .await
82 .map_err(|e| MemoryError::sqlite("soft delete failed", e))?;
83
84 Ok(result.rows_affected() > 0)
85 }
86
87 pub async fn get_facts(&self, sender_id: &str) -> Result<Vec<(String, String)>, MemoryError> {
89 let rows: Vec<(String, String)> = sqlx::query_as(
90 "SELECT key, value FROM facts \
91 WHERE sender_id = ? AND deleted_at IS NULL ORDER BY key",
92 )
93 .bind(sender_id)
94 .fetch_all(&self.pool)
95 .await
96 .map_err(|e| MemoryError::sqlite("query failed", e))?;
97
98 Ok(rows)
99 }
100
101 pub async fn delete_facts(
106 &self,
107 sender_id: &str,
108 key: Option<&str>,
109 ) -> Result<u64, MemoryError> {
110 let result = if let Some(k) = key {
111 sqlx::query("DELETE FROM facts WHERE sender_id = ? AND key = ?")
112 .bind(sender_id)
113 .bind(k)
114 .execute(&self.pool)
115 .await
116 } else {
117 sqlx::query("DELETE FROM facts WHERE sender_id = ?")
118 .bind(sender_id)
119 .execute(&self.pool)
120 .await
121 };
122
123 result
124 .map(|r| r.rows_affected())
125 .map_err(|e| MemoryError::sqlite("delete failed", e))
126 }
127
128 pub async fn soft_delete_facts(
132 &self,
133 sender_id: &str,
134 key: Option<&str>,
135 ) -> Result<u64, MemoryError> {
136 let result = if let Some(k) = key {
137 sqlx::query(
138 "UPDATE facts SET deleted_at = datetime('now') \
139 WHERE sender_id = ? AND key = ? AND deleted_at IS NULL",
140 )
141 .bind(sender_id)
142 .bind(k)
143 .execute(&self.pool)
144 .await
145 } else {
146 sqlx::query(
147 "UPDATE facts SET deleted_at = datetime('now') \
148 WHERE sender_id = ? AND deleted_at IS NULL",
149 )
150 .bind(sender_id)
151 .execute(&self.pool)
152 .await
153 };
154
155 result
156 .map(|r| r.rows_affected())
157 .map_err(|e| MemoryError::sqlite("soft delete failed", e))
158 }
159
160 pub async fn list_soft_deleted_facts(
164 &self,
165 sender_id: &str,
166 ) -> Result<Vec<(String, String, String)>, MemoryError> {
167 let rows: Vec<(String, String, String)> = sqlx::query_as(
168 "SELECT key, value, deleted_at FROM facts \
169 WHERE sender_id = ? AND deleted_at IS NOT NULL \
170 ORDER BY deleted_at DESC",
171 )
172 .bind(sender_id)
173 .fetch_all(&self.pool)
174 .await
175 .map_err(|e| MemoryError::sqlite("query failed", e))?;
176
177 Ok(rows)
178 }
179
180 pub async fn get_all_facts(&self) -> Result<Vec<(String, String)>, MemoryError> {
183 let rows: Vec<(String, String)> = sqlx::query_as(
184 "SELECT key, value FROM facts \
185 WHERE key != 'welcomed' AND deleted_at IS NULL ORDER BY key",
186 )
187 .fetch_all(&self.pool)
188 .await
189 .map_err(|e| MemoryError::sqlite("query failed", e))?;
190
191 Ok(rows)
192 }
193
194 pub async fn get_all_facts_by_key(
197 &self,
198 key: &str,
199 ) -> Result<Vec<(String, String)>, MemoryError> {
200 let rows: Vec<(String, String)> = sqlx::query_as(
201 "SELECT sender_id, value FROM facts \
202 WHERE key = ? AND deleted_at IS NULL ORDER BY sender_id",
203 )
204 .bind(key)
205 .fetch_all(&self.pool)
206 .await
207 .map_err(|e| MemoryError::sqlite("get facts by key failed", e))?;
208 Ok(rows)
209 }
210
211 pub async fn is_new_user(&self, sender_id: &str) -> Result<bool, MemoryError> {
214 let row: Option<(String,)> = sqlx::query_as(
215 "SELECT value FROM facts \
216 WHERE sender_id = ? AND key = 'welcomed' AND deleted_at IS NULL",
217 )
218 .bind(sender_id)
219 .fetch_optional(&self.pool)
220 .await
221 .map_err(|e| MemoryError::sqlite("query failed", e))?;
222
223 Ok(row.is_none())
224 }
225
226 pub async fn resolve_sender_id(&self, sender_id: &str) -> Result<String, MemoryError> {
230 let row: Option<(String,)> = sqlx::query_as(
231 "SELECT canonical_sender_id FROM user_aliases WHERE alias_sender_id = ?",
232 )
233 .bind(sender_id)
234 .fetch_optional(&self.pool)
235 .await
236 .map_err(|e| MemoryError::sqlite("resolve alias failed", e))?;
237
238 Ok(row.map(|(id,)| id).unwrap_or_else(|| sender_id.to_string()))
239 }
240
241 pub async fn create_alias(
243 &self,
244 alias_id: &str,
245 canonical_id: &str,
246 ) -> Result<(), MemoryError> {
247 sqlx::query(
248 "INSERT OR IGNORE INTO user_aliases (alias_sender_id, canonical_sender_id) \
249 VALUES (?, ?)",
250 )
251 .bind(alias_id)
252 .bind(canonical_id)
253 .execute(&self.pool)
254 .await
255 .map_err(|e| MemoryError::sqlite("create alias failed", e))?;
256
257 Ok(())
258 }
259
260 pub async fn find_canonical_user(
263 &self,
264 exclude_sender_id: &str,
265 ) -> Result<Option<String>, MemoryError> {
266 let row: Option<(String,)> = sqlx::query_as(
267 "SELECT sender_id FROM facts \
268 WHERE key = 'welcomed' AND sender_id != ? AND deleted_at IS NULL LIMIT 1",
269 )
270 .bind(exclude_sender_id)
271 .fetch_optional(&self.pool)
272 .await
273 .map_err(|e| MemoryError::sqlite("query failed", e))?;
274
275 Ok(row.map(|(id,)| id))
276 }
277
278 pub async fn store_limitation(
282 &self,
283 title: &str,
284 description: &str,
285 proposed_plan: &str,
286 ) -> Result<bool, MemoryError> {
287 let id = Uuid::new_v4().to_string();
288 let result = sqlx::query(
289 "INSERT OR IGNORE INTO limitations (id, title, description, proposed_plan) \
290 VALUES (?, ?, ?, ?)",
291 )
292 .bind(&id)
293 .bind(title)
294 .bind(description)
295 .bind(proposed_plan)
296 .execute(&self.pool)
297 .await
298 .map_err(|e| MemoryError::sqlite("store limitation failed", e))?;
299
300 Ok(result.rows_affected() > 0)
301 }
302
303 pub async fn get_open_limitations(&self) -> Result<Vec<(String, String, String)>, MemoryError> {
305 let rows: Vec<(String, String, String)> = sqlx::query_as(
306 "SELECT title, description, proposed_plan FROM limitations \
307 WHERE status = 'open' ORDER BY created_at ASC",
308 )
309 .fetch_all(&self.pool)
310 .await
311 .map_err(|e| MemoryError::sqlite("get open limitations failed", e))?;
312
313 Ok(rows)
314 }
315}