1+ """Test to verify that issue #254 is fixed.
2+
3+ Issue #254: Foreign key constraint failures when deleting projects with related entities.
4+
5+ The issue was that when migration 647e7a75e2cd recreated the project table,
6+ it did not re-establish the foreign key constraint from entity.project_id to project.id
7+ with CASCADE DELETE, causing foreign key constraint failures when trying to delete
8+ projects that have related entities.
9+
10+ Migration a1b2c3d4e5f6 was created to fix this by adding the missing foreign key
11+ constraint with CASCADE DELETE behavior.
12+
13+ This test file verifies that the fix works correctly in production databases
14+ that have had the migration applied.
15+ """
16+ from datetime import datetime , timezone
17+
18+ import pytest
19+
20+ from basic_memory .services .project_service import ProjectService
21+
22+
23+ #@pytest.mark.skip(reason="Issue #254 not fully resolved yet - foreign key constraint errors still occur")
24+ @pytest .mark .asyncio
25+ async def test_issue_254_foreign_key_constraint_fix (project_service : ProjectService , tmp_path ):
26+ """Test to verify issue #254 is fixed: project removal with foreign key constraints.
27+
28+ This test reproduces the exact scenario from issue #254:
29+ 1. Create a project
30+ 2. Create entities, observations, and relations linked to that project
31+ 3. Attempt to remove the project
32+ 4. Verify it succeeds without "FOREIGN KEY constraint failed" errors
33+ 5. Verify all related data is properly cleaned up via CASCADE DELETE
34+
35+ Once issue #254 is fully fixed, remove the @pytest.mark.skip decorator.
36+ """
37+ test_project_name = "issue-254-verification"
38+ test_project_path = str (tmp_path / "issue-254-verification" )
39+
40+ # Step 1: Create test project
41+ await project_service .add_project (test_project_name , test_project_path )
42+ project = await project_service .get_project (test_project_name )
43+ assert project is not None , "Project should be created successfully"
44+
45+ # Step 2: Create related entities that would cause foreign key constraint issues
46+ from basic_memory .repository .entity_repository import EntityRepository
47+ from basic_memory .repository .observation_repository import ObservationRepository
48+ from basic_memory .repository .relation_repository import RelationRepository
49+
50+ entity_repo = EntityRepository (project_service .repository .session_maker , project_id = project .id )
51+ obs_repo = ObservationRepository (project_service .repository .session_maker , project_id = project .id )
52+ rel_repo = RelationRepository (project_service .repository .session_maker , project_id = project .id )
53+
54+ # Create entity
55+ entity_data = {
56+ "title" : "Issue 254 Test Entity" ,
57+ "entity_type" : "note" ,
58+ "content_type" : "text/markdown" ,
59+ "project_id" : project .id ,
60+ "permalink" : "issue-254-entity" ,
61+ "file_path" : "issue-254-entity.md" ,
62+ "checksum" : "issue254test" ,
63+ "created_at" : datetime .now (timezone .utc ),
64+ "updated_at" : datetime .now (timezone .utc ),
65+ }
66+ entity = await entity_repo .create (entity_data )
67+
68+ # Create observation linked to entity
69+ observation_data = {
70+ "entity_id" : entity .id ,
71+ "content" : "This observation should be cascade deleted" ,
72+ "category" : "test"
73+ }
74+ observation = await obs_repo .create (observation_data )
75+
76+ # Create relation involving the entity
77+ relation_data = {
78+ "from_id" : entity .id ,
79+ "to_name" : "some-other-entity" ,
80+ "relation_type" : "relates-to"
81+ }
82+ relation = await rel_repo .create (relation_data )
83+
84+ # Step 3: Attempt to remove the project
85+ # This is where issue #254 manifested - should NOT raise "FOREIGN KEY constraint failed"
86+ try :
87+ await project_service .remove_project (test_project_name )
88+ except Exception as e :
89+ if "FOREIGN KEY constraint failed" in str (e ):
90+ pytest .fail (
91+ f"Issue #254 not fixed - foreign key constraint error still occurs: { e } . "
92+ f"The migration a1b2c3d4e5f6 may not have been applied correctly or "
93+ f"the CASCADE DELETE constraint is not working as expected."
94+ )
95+ else :
96+ # Re-raise unexpected errors
97+ raise
98+
99+ # Step 4: Verify project was successfully removed
100+ removed_project = await project_service .get_project (test_project_name )
101+ assert removed_project is None , "Project should have been removed"
102+
103+ # Step 5: Verify related data was cascade deleted
104+ remaining_entity = await entity_repo .find_by_id (entity .id )
105+ assert remaining_entity is None , "Entity should have been cascade deleted"
106+
107+ remaining_observation = await obs_repo .find_by_id (observation .id )
108+ assert remaining_observation is None , "Observation should have been cascade deleted"
109+
110+ remaining_relation = await rel_repo .find_by_id (relation .id )
111+ assert remaining_relation is None , "Relation should have been cascade deleted"
112+
113+
114+ @pytest .mark .asyncio
115+ async def test_issue_254_reproduction (project_service : ProjectService , tmp_path ):
116+ """Test that reproduces issue #254 to document the current state.
117+
118+ This test demonstrates the current behavior and will fail until the issue is fixed.
119+ It serves as documentation of what the problem was.
120+ """
121+ test_project_name = "issue-254-reproduction"
122+ test_project_path = str (tmp_path / "issue-254-reproduction" )
123+
124+ # Create project and entity
125+ await project_service .add_project (test_project_name , test_project_path )
126+ project = await project_service .get_project (test_project_name )
127+
128+ from basic_memory .repository .entity_repository import EntityRepository
129+ entity_repo = EntityRepository (project_service .repository .session_maker , project_id = project .id )
130+
131+ entity_data = {
132+ "title" : "Reproduction Entity" ,
133+ "entity_type" : "note" ,
134+ "content_type" : "text/markdown" ,
135+ "project_id" : project .id ,
136+ "permalink" : "reproduction-entity" ,
137+ "file_path" : "reproduction-entity.md" ,
138+ "checksum" : "repro123" ,
139+ "created_at" : datetime .now (timezone .utc ),
140+ "updated_at" : datetime .now (timezone .utc ),
141+ }
142+ entity = await entity_repo .create (entity_data )
143+
144+ # This should eventually work without errors once issue #254 is fixed
145+ #with pytest.raises(Exception) as exc_info:
146+ await project_service .remove_project (test_project_name )
147+
148+ # Document the current error for tracking
149+ # error_message = str(exc_info.value)
150+ # assert any(keyword in error_message for keyword in [
151+ # "FOREIGN KEY constraint failed",
152+ # "constraint",
153+ # "integrity"
154+ # ]), f"Expected foreign key or integrity constraint error, got: {error_message}"
0 commit comments