Skip to content

fix(sqlite): repair search docs FTS maintenance#1588

Open
yyhhyyyyyy wants to merge 1 commit intodevfrom
fix/search-documents-fts
Open

fix(sqlite): repair search docs FTS maintenance#1588
yyhhyyyyyy wants to merge 1 commit intodevfrom
fix/search-documents-fts

Conversation

@yyhhyyyyyy
Copy link
Copy Markdown
Collaborator

@yyhhyyyyyy yyhhyyyyyy commented May 7, 2026

repair search docs FTS maintenance
fix Error occurred in handler for 'deepchat:route:invoke': SqliteError: database disk image is malformed

Summary by CodeRabbit

  • Bug Fixes
    • Improved search reliability with enhanced schema compatibility checks and automatic fallback to alternative search methods when needed.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

DeepChatSearchDocumentsTable refactors FTS5 virtual table management with configurable constants, schema-compatibility detection helpers, transactional initialization with optional rebuild, explicit trigger lifecycle methods, and gated delete operations that respect FTS availability state.

Changes

FTS5 Schema Management Refactor

Layer / File(s) Summary
FTS Constants & Configuration
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Adds FTS_TABLE_NAME constant for the virtual table and TRIGGER_NAMES array defining the ordered list of triggers (AFTER INSERT, AFTER DELETE, AFTER UPDATE) used for schema validation and lifecycle.
FTS Availability State
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Introduces ftsUnavailable instance field to short-circuit FTS checks after initialization failure.
Schema Detection & Validation Helpers
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Replaces single-table existence check with rich detection: isFtsTableExists, getFtsTableSql, isFtsTableCompatible (validates fts5/content/content_rowid keywords), and areFtsTriggersExist (checks all required triggers).
Trigger Lifecycle Management
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Implements dropFtsTriggers and ensureFtsTriggers to manage AFTER INSERT/DELETE/UPDATE triggers that synchronize main table changes into the FTS virtual table.
Transactional Bootstrap
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Reworks ensureFtsTable to run in a transaction: detects schema incompatibility, drops and recreates FTS table when needed, ensures all triggers, conditionally rebuilds index, and sets ftsUnavailable flag with warning log on any error.
Delete Path Integration
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Simplifies delete and deleteBySession to remove redundant FTS refresh logic and explicitly gate FTS operations on availability.
Index Rebuild
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts
Updates FTS rebuild logic to use the new FTS_TABLE_NAME constant instead of hardcoded string.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A FTS tale in the database
Tables dance with triggers bright,
Schema checks ensure they're right,
Bootstrap builds with care and grace,
When FTS fails, we fall to LIKE,
Rabbit hopped through all the code!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(sqlite): repair search docs FTS maintenance' directly and specifically describes the main change: repairing FTS maintenance for search documents in SQLite.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/search-documents-fts

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts (1)

75-81: ⚡ Quick win

isFtsAvailable() re-queries sqlite_master on every search — consider caching the ready state.

After ensureFtsTable() completes successfully, ftsUnavailable is false but isFtsAvailable() still calls hasCompatibleFtsTable(), which issues a sqlite_master read on every searchFts() invocation. The ftsUnavailable fast-exit only fires on the error path.

The simplest fix is to introduce a separate positive flag:

♻️ Proposed refactor
-  private ftsUnavailable = false
+  private ftsUnavailable = false
+  private ftsReady = false

   isFtsAvailable(): boolean {
-    if (this.ftsUnavailable) {
-      return false
-    }
-
-    return this.hasCompatibleFtsTable()
+    if (this.ftsReady) return true
+    if (this.ftsUnavailable) return false
+    return this.hasCompatibleFtsTable()
   }
   // In ensureFtsTable(), after the transaction:
-      this.ftsUnavailable = false
+      this.ftsUnavailable = false
+      this.ftsReady = true

The hasCompatibleFtsTable() guard remains useful for the first call before createTable() runs, and the positive ftsReady flag short-circuits all subsequent hot-path calls.

🤖 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 `@src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts` around
lines 75 - 81, isFtsAvailable() currently re-queries sqlite_master on every
search because after ensureFtsTable() succeeds it still calls
hasCompatibleFtsTable(); add a positive cached flag (e.g., ftsReady) that
ensureFtsTable() sets to true on success and have isFtsAvailable() return false
if ftsUnavailable is true, true if ftsReady is true, otherwise fall back to
hasCompatibleFtsTable(); update searchFts() hot path to rely on isFtsAvailable()
so subsequent searches short-circuit without repeated sqlite_master reads.
🤖 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.

Nitpick comments:
In `@src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts`:
- Around line 75-81: isFtsAvailable() currently re-queries sqlite_master on
every search because after ensureFtsTable() succeeds it still calls
hasCompatibleFtsTable(); add a positive cached flag (e.g., ftsReady) that
ensureFtsTable() sets to true on success and have isFtsAvailable() return false
if ftsUnavailable is true, true if ftsReady is true, otherwise fall back to
hasCompatibleFtsTable(); update searchFts() hot path to rely on isFtsAvailable()
so subsequent searches short-circuit without repeated sqlite_master reads.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8aece51f-cafe-4677-b985-a2e5628b0429

📥 Commits

Reviewing files that changed from the base of the PR and between 77197c8 and 00cd5df.

📒 Files selected for processing (1)
  • src/main/presenter/sqlitePresenter/tables/deepchatSearchDocuments.ts

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