From c816bfab20fe77419a7f2677fb0d90f72bab22f1 Mon Sep 17 00:00:00 2001 From: liuhao1024 Date: Sat, 5 Sep 2026 21:27:33 +0800 Subject: [PATCH] fix(state): escape underscores in the cjk family exclusion LIKE pattern Review feedback on #103657: the sibling clauses in the same statement declare ESCAPE, and the trash enumeration two blocks up escapes its underscores via replace. Use the same escaped ESCAPE form so every underscore in the statement is a literal match instead of a single-character wildcard. Behavior on the fixed schema is unchanged (same enumeration split); this is consistency plus defense against future lookalike table names. Also reword the exclusion comment to the verified failure mechanism: fts5 xRename renames the whole shadow family in one step, so sweeping the cjk vtable aborts the loop on the next shadow entry and drags the _config table (read by the vtable constructor) into the trash family. --- hermes_state_search.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hermes_state_search.py b/hermes_state_search.py index 3cd3427862..5986a4f840 100644 --- a/hermes_state_search.py +++ b/hermes_state_search.py @@ -532,9 +532,11 @@ class SessionSearchMixin: "AND (name LIKE 'messages_fts_%' ESCAPE '\\' " "OR name LIKE 'messages_fts_trigram_%' ESCAPE '\\') " # messages_fts_cjk* is an independent v23+ index, not part of the - # demoted legacy layout: renaming it (or its shadow tables) breaks - # the vtable constructor chain (#103647). - "AND name NOT LIKE 'messages_fts_cjk%'" + # demoted legacy layout: fts5's xRename renames the entire shadow + # family in one step, so sweeping the cjk vtable here aborts the + # loop on the next cjk shadow entry and drags _config — needed by + # the vtable constructor — into the trash family (#103647). + "AND name NOT LIKE 'messages\\_fts\\_cjk%' ESCAPE '\\'" ).fetchall(): conn.execute(f"ALTER TABLE {row[0]} RENAME TO fts_v22_trash_{row[0]}") # Claim the backfill BEFORE the empty v23 tables exist so a crash before