diff --git a/cloud/db.py b/cloud/db.py index 9b08d57..0eda9e1 100644 --- a/cloud/db.py +++ b/cloud/db.py @@ -415,6 +415,13 @@ _OR_REPLACE_PK = { "project_members": ("project_id", "user_id"), "slack_users": ("slack_id",), "github_app_config": ("id",), + # 自动记忆三张表:主键登记缺失时 Postgres 翻译退化为 + # ON CONFLICT DO NOTHING,首写之后的所有更新静默丢弃 + # (2026-10-28 生产实测:提取日志永远停在首写原因, + # 改设置同理;SQLite 原生 OR REPLACE 测不出来)。 + "memory_settings": ("user_id",), + "task_memory_flags": ("task_id",), + "memory_extraction_log": ("task_id",), } _IDENTITY_TABLES = frozenset( diff --git a/cloud/tests/test_postgres_backend.py b/cloud/tests/test_postgres_backend.py index 8166ab3..b292b1c 100644 --- a/cloud/tests/test_postgres_backend.py +++ b/cloud/tests/test_postgres_backend.py @@ -198,6 +198,33 @@ class PlaceholderTranslationTestCase(unittest.TestCase): self.assertIn("%s", translated) self.assertNotIn("?", translated) + def test_auto_memory_tables_replace_updates_not_ignores(self): + # 2026-10-28 生产教训:这三张表未登记主键时翻译退化为 + # ON CONFLICT DO NOTHING,首写之后的更新静默丢弃;SQLite + # 原生 OR REPLACE 测不出来,必须在翻译层断言。 + cases = [ + ("INSERT OR REPLACE INTO memory_settings" + "(user_id, generate_memories, updated_at) VALUES(?, ?, ?)", + "ON CONFLICT (user_id) DO UPDATE SET", + "generate_memories = EXCLUDED.generate_memories"), + ("INSERT OR REPLACE INTO task_memory_flags" + "(task_id, use_memories, generate_memories, updated_at)" + " VALUES(?, ?, ?, ?)", + "ON CONFLICT (task_id) DO UPDATE SET", + "use_memories = EXCLUDED.use_memories"), + ("INSERT OR REPLACE INTO memory_extraction_log" + "(task_id, status, reason, processed_at) VALUES(?, ?, ?, ?)", + "ON CONFLICT (task_id) DO UPDATE SET", + "status = EXCLUDED.status"), + ] + for sql, conflict, setter in cases: + translated, kind = _translate_sql(sql) + self.assertEqual(kind, "normal") + self.assertIn(conflict, translated) + self.assertIn(setter, translated) + self.assertNotIn("DO NOTHING", translated) + self.assertNotIn("OR REPLACE", translated) + def test_autoincrement_becomes_identity(self): translated, _ = _translate_sql( "CREATE TABLE t(id INTEGER PRIMARY KEY AUTOINCREMENT, x TEXT)")