Skip to content

Bugfix/orphaned rows cascade delete - #1407

Open
AbiramiR-27 wants to merge 9 commits into
AOSSIE-Org:mainfrom
AbiramiR-27:bugfix/orphaned-rows-cascade-delete
Open

Bugfix/orphaned rows cascade delete#1407
AbiramiR-27 wants to merge 9 commits into
AOSSIE-Org:mainfrom
AbiramiR-27:bugfix/orphaned-rows-cascade-delete

Conversation

@AbiramiR-27

@AbiramiR-27 AbiramiR-27 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Addressed Issues:

Fixes #1405

Screenshots/Recordings:

N/A (This is a database integrity update).

Additional Notes:

Both the image_embeddings and image_semantic_labels tables define foreign key constraints with ON DELETE CASCADE referencing images(id). This configuration is intended to automatically delete embeddings and semantic labels when an image is deleted.

However, both modules established database connections using the private _connect() helper from app.database.images, which does not run PRAGMA foreign_keys = ON;. Because SQLite disables foreign key constraints by default, image deletions left orphaned records in these tables.

Changes made in this PR:

  • Refactored backend/app/database/image_embeddings.py to use the get_db_connection() context manager from app.database.connection.
  • Refactored backend/app/database/semantic_labels.py to use the get_db_connection() context manager.
  • Updated backend/tests/test_image_embeddings.py's _isolated_db test fixture to patch app.database.connection.DATABASE_PATH, redirecting the context manager to the test database and ensuring all tests pass cleanly.
  • Updated backend/tests/test_semantic_labels.py's _isolated_db test fixture to patch app.database.connection.DATABASE_PATH, ensuring the new semantic search tests pass cleanly.

AI Usage Disclosure:

  • This PR does not contain AI-generated code at all.
  • This PR contains AI-generated code. I have read the AI Usage Policy and this PR complies with this policy. I have tested the code locally and I am responsible for it.

I have used the following AI models and tools: Gemini 3.5 Flash .

Checklist

  • My PR addresses a single issue, fixes a single bug or makes a single improvement.
  • My code follows the project's code style and conventions
  • If applicable, I have made corresponding changes or additions to the documentation
  • If applicable, I have made corresponding changes or additions to tests
  • My changes generate no new warnings or errors
  • I have joined the Discord server and I will share a link to this PR with the project maintainers there
  • I have read the Contribution Guidelines
  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.
  • I have filled this PR template completely and carefully, and I understand that my PR may be closed without review otherwise.

Summary by CodeRabbit

  • Bug Fixes
    • Improved SQLite connection/transaction handling across image embeddings and semantic label database helpers for more reliable reads/writes.
    • Enhanced image deletion and favorite toggling to use safer, context-managed connections and consistent chunked deletion behavior.
  • Tests
    • Strengthened test database isolation by redirecting all shared database connections to the per-test SQLite file.
    • Added a regression test covering cascading deletes from images to embeddings and related class records.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cb946d73-890e-48c2-af54-a30fe43b3208

📥 Commits

Reviewing files that changed from the base of the PR and between dc343ae and 7417b6b.

📒 Files selected for processing (2)
  • backend/app/database/connection.py
  • backend/app/database/images.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/app/database/connection.py

Walkthrough

Database helpers now use get_db_connection() context managers. Embedding retrieval is simplified, image deletion uses the shared connection path, and test fixtures patch the shared database path for isolated SQLite tests.

Changes

Database connection migration

Layer / File(s) Summary
Shared connection path
backend/app/database/connection.py
Database connections now resolve the current database path dynamically, including test-time path overrides.
Embedding and semantic-label database access
backend/app/database/image_embeddings.py, backend/app/database/semantic_labels.py
Embedding and semantic-label operations use context-managed connections; embedding retrieval builds NumPy matrices directly from stored blobs.
Image deletion and isolated validation
backend/app/database/images.py, backend/tests/test_image_embeddings.py, backend/tests/test_semantic_labels.py
Image deletion and favourite toggling use shared connection handling, while tests verify isolated paths and cascading deletion of dependent rows.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: Python

Poem

I’m a rabbit with connections neat,
Contexts close them, quick and sweet.
Embeddings stack in arrays bright,
Clean test databases hop tonight. 🐇

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the primary fix: orphaned rows from cascade deletes.
Linked Issues check ✅ Passed The refactor uses get_db_connection in the affected modules and adds tests that verify cascades remove orphans.
Out of Scope Changes check ✅ Passed The changes stay centered on SQLite connection handling and cascade-delete behavior, with test support to match.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/tests/test_image_embeddings.py`:
- Line 40: The cascade test should execute DELETE through get_db_connection()
rather than _connect(), and the application image-deletion path should use
get_db_connection() as well. Update the relevant test delete block and
production image-deletion method, preserving the existing cascade behavior and
connection lifecycle.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4d90432-c4fe-4078-8c32-3755a3d450ef

📥 Commits

Reviewing files that changed from the base of the PR and between 859ac7a and c14ec24.

📒 Files selected for processing (4)
  • backend/app/database/image_embeddings.py
  • backend/app/database/semantic_labels.py
  • backend/tests/test_image_embeddings.py
  • backend/tests/test_semantic_labels.py

Comment thread backend/tests/test_image_embeddings.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/app/database/images.py (1)

470-479: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add a regression test for cascade deletion.

Verify that deleting an image also removes its related image_embeddings and image_semantic_labels rows. The supplied coverage shows schema setup but not this end-to-end deletion contract. As per path instructions, critical functionality should be covered by automated tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/database/images.py` around lines 470 - 479, Add a regression test
covering the image deletion flow that executes the relevant deletion operation
and verifies the associated image_embeddings and image_semantic_labels rows are
also removed. Reuse the existing database/schema setup and image deletion
symbols exposed by the test suite, and assert both related tables are empty for
the deleted image while preserving unrelated records.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/database/images.py`:
- Line 13: Update _connect and the image helper operations to use the same
shared connection path as db_delete_images_by_ids via get_db_connection,
removing reliance on the module-level DATABASE_PATH and direct sqlite3.connect
calls. Ensure setup, reads, and deletes all target the manager-selected
database, including when tests patch the shared manager.

---

Nitpick comments:
In `@backend/app/database/images.py`:
- Around line 470-479: Add a regression test covering the image deletion flow
that executes the relevant deletion operation and verifies the associated
image_embeddings and image_semantic_labels rows are also removed. Reuse the
existing database/schema setup and image deletion symbols exposed by the test
suite, and assert both related tables are empty for the deleted image while
preserving unrelated records.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a1a90b1a-ccfe-4c62-b2f0-098f382f319c

📥 Commits

Reviewing files that changed from the base of the PR and between c14ec24 and c66a73c.

📒 Files selected for processing (2)
  • backend/app/database/images.py
  • backend/tests/test_image_embeddings.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/tests/test_image_embeddings.py

Comment thread backend/app/database/images.py
@AbiramiR-27

AbiramiR-27 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

@rohan-pandeyy Could u pls review this pr?

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This PR has merge conflicts.

Please resolve the merge conflicts before review.

Your PR will only be reviewed by a maintainer after all conflicts have been resolved.

📺 Watch this video to understand why conflicts occur and how to resolve them:
https://www.youtube.com/watch?v=Sqsz1-o7nXk

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/app/database/images.py (1)

24-27: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Wire SQLITE_ID_CHUNK into db_delete_images_by_ids.

db_delete_images_by_ids() builds DELETE FROM images WHERE id IN (...) with one placeholder per ID, so calls with 999+ IDs can exceed SQLite’s pre-3.32 host parameter limit even though SQLITE_ID_CHUNK = 500 is declared but unused. Split image_ids into chunks before constructing the IN clause.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/database/images.py` around lines 24 - 27, Update
db_delete_images_by_ids to split image_ids into SQLITE_ID_CHUNK-sized batches
before constructing the DELETE IN clauses, executing the deletion for each batch
while preserving existing behavior for smaller inputs.
🧹 Nitpick comments (1)
backend/app/database/connection.py (1)

14-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Wrap the long docstring line.

Line 14 exceeds PEP 8’s recommended 79-character limit. Reflow the docstring without changing behavior.

Proposed fix
 def get_database_path() -> str:
-    """Resolve the active database path dynamically, supporting various test patching styles."""
+    """Resolve the active database path dynamically.
+
+    Supports various test patching styles.
+    """

As per path instructions, Python files must follow PEP 8.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/database/connection.py` at line 14, Wrap the long module
docstring near the database-path resolution code across multiple lines to stay
within PEP 8’s 79-character limit, preserving its wording and behavior.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@backend/app/database/images.py`:
- Around line 24-27: Update db_delete_images_by_ids to split image_ids into
SQLITE_ID_CHUNK-sized batches before constructing the DELETE IN clauses,
executing the deletion for each batch while preserving existing behavior for
smaller inputs.

---

Nitpick comments:
In `@backend/app/database/connection.py`:
- Line 14: Wrap the long module docstring near the database-path resolution code
across multiple lines to stay within PEP 8’s 79-character limit, preserving its
wording and behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fcd4dd05-f2ad-4855-a6c0-036ae668b3ba

📥 Commits

Reviewing files that changed from the base of the PR and between cdb3dee and dc343ae.

📒 Files selected for processing (4)
  • backend/app/database/connection.py
  • backend/app/database/image_embeddings.py
  • backend/app/database/images.py
  • backend/tests/test_image_embeddings.py

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.

BUG: Orphaned Rows in image_embeddings and semantic_labels on Image Deletion

1 participant