From d918c18bb2ee3b89d3a53cf0fbdfaf9f104ea597 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 10 Sep 2026 16:08:19 -0700 Subject: [PATCH] Escape literal table names in FTS detection patterns --- datasette/utils/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index 3112dc9f..59ff877c 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -600,13 +600,14 @@ def detect_fts(conn, table): def detect_fts_sql(table): + escaped_table = table.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_") return ( r""" select name from sqlite_master where rootpage = 0 and ( - sql like :fts_double_quoted - or sql like :fts_bracket_quoted + sql like :fts_double_quoted escape char(92) + or sql like :fts_bracket_quoted escape char(92) or ( tbl_name = :table and sql like '%VIRTUAL TABLE%USING FTS%' @@ -614,8 +615,8 @@ def detect_fts_sql(table): ) """, { - "fts_double_quoted": f'%VIRTUAL TABLE%USING FTS%content="{table}"%', - "fts_bracket_quoted": f"%VIRTUAL TABLE%USING FTS%content=[{table}]%", + "fts_double_quoted": f'%VIRTUAL TABLE%USING FTS%content="{escaped_table}"%', + "fts_bracket_quoted": f"%VIRTUAL TABLE%USING FTS%content=[{escaped_table}]%", "table": table, }, )