Skip to content

fix: flush implicit transaction before BEGIN IMMEDIATE (#135)#162

Open
azizur100389 wants to merge 1 commit intotirth8205:mainfrom
azizur100389:claude/interesting-johnson
Open

fix: flush implicit transaction before BEGIN IMMEDIATE (#135)#162
azizur100389 wants to merge 1 commit intotirth8205:mainfrom
azizur100389:claude/interesting-johnson

Conversation

@azizur100389
Copy link
Copy Markdown

Summary

Root Cause

Python's sqlite3 with default isolation_level="" auto-begins a DEFERRED transaction on the first DML. In incremental_update and full_build, remove_file_data() issues DELETE statements for deleted/stale files, silently opening an implicit transaction. The subsequent store_file_nodes_edges() then executes BEGIN IMMEDIATE inside that already-open transaction, which SQLite rejects.

Fix

Check self._conn.in_transaction before BEGIN IMMEDIATE and commit any pending implicit transaction. This preserves atomic replace semantics while being robust against prior implicit transaction state. The guard is a no-op when no implicit transaction is open.

Tests Added

  • test_store_after_remove_no_transaction_error — direct GraphStore unit test
  • test_incremental_deleted_and_modified_files — end-to-end incremental update with mixed deletes and modifications
  • test_full_build_stale_files_then_parse — end-to-end full build with stale file purging

Test Plan

  • All 3 new regression tests pass
  • All existing test_graph.py and test_incremental.py tests pass (46/46)
  • ruff check clean on all changed files

When git diff includes deleted files, remove_file_data() DELETEs open
an implicit DEFERRED transaction. The subsequent store_file_nodes_edges()
call then fails with "cannot start a transaction within a transaction"
because BEGIN IMMEDIATE cannot nest inside DEFERRED.

Commit any pending implicit transaction before BEGIN IMMEDIATE.
Add regression tests for both incremental_update and full_build paths.
@azizur100389 azizur100389 force-pushed the claude/interesting-johnson branch from 18a9c1b to bcb3dad Compare April 8, 2026 22:12
ghiemer added a commit to ghiemer/code-review-graph that referenced this pull request Apr 10, 2026
…205#135, tirth8205#181)

Python's sqlite3 with default isolation_level="" silently opens a
DEFERRED transaction on the first DML statement. When remove_file_data()
is called for stale/deleted files, the DELETE statements open an implicit
transaction that is never committed. The subsequent
store_file_nodes_edges() then executes BEGIN IMMEDIATE inside that
already-open transaction, causing:

  sqlite3.OperationalError: cannot start a transaction within a transaction

This affects both full_build (stale-file purge loop) and
incremental_update (deleted-file handling).

Fix:
- graph.py: Add in_transaction guard before BEGIN IMMEDIATE in
  store_file_nodes_edges() to flush any pending implicit transaction
- graph.py: Add public rollback() method to GraphStore
- incremental.py: Commit after stale-file purge loop in full_build()
- incremental.py: Commit after deleted-file removal in incremental_update()

Tests:
- test_store_after_remove_no_transaction_error (single remove → store)
- test_store_after_multiple_removes_no_transaction_error (bulk removes → store)

Closes tirth8205#135, tirth8205#181, relates to tirth8205#162, tirth8205#193, tirth8205#94

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant