From b8036ab59f36db2ea732c53c420b7e1989c8d6e8 Mon Sep 17 00:00:00 2001 From: Roland Walker Date: Tue, 10 Feb 2026 05:20:56 -0500 Subject: [PATCH] fix comments breaking destructive UPDATE detection An inline comment could change the indexing of the tokens by introducing whitespace. The re.sub() fix is brutal but doesn't change the tokens. The fix also applies to extra whitespace without comments, which alone could also break the query_is_single_table_update() detection. --- changelog.md | 1 + mycli/packages/parseutils.py | 7 ++++--- test/test_parseutils.py | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 146ef43e..b0c1abaa 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,7 @@ Bug Fixes -------- * Reduce duplicated `--checkup` output. * Handle errors generating completions on stored procedures. +* Fix whitespace/inline comments breaking destructive `UPDATE … WHERE` statement detection. Internal diff --git a/mycli/packages/parseutils.py b/mycli/packages/parseutils.py index 17df81d8..9833f8cb 100644 --- a/mycli/packages/parseutils.py +++ b/mycli/packages/parseutils.py @@ -359,10 +359,11 @@ def query_has_where_clause(query: str) -> bool: # todo: handle "UPDATE LOW_PRIORITY" and "UPDATE IGNORE" def query_is_single_table_update(query: str) -> bool: """Check if a query is a simple single-table UPDATE.""" - cleaned_query = sqlparse.format(query, strip_comments=True) - if not cleaned_query: + cleaned_query_for_parsing_only = sqlparse.format(query, strip_comments=True) + cleaned_query_for_parsing_only = re.sub(r'\s+', ' ', cleaned_query_for_parsing_only) + if not cleaned_query_for_parsing_only: return False - parsed = sqlparse.parse(cleaned_query) + parsed = sqlparse.parse(cleaned_query_for_parsing_only) if not parsed: return False statement = parsed[0] diff --git a/test/test_parseutils.py b/test/test_parseutils.py index aa0b4632..cbdb790a 100644 --- a/test/test_parseutils.py +++ b/test/test_parseutils.py @@ -157,6 +157,11 @@ def test_is_destructive_update_with_where_clause(): assert is_destructive(["update"], sql) is False +def test_is_destructive_update_with_where_clause_and_comment(): + sql = "use test;\nshow databases;\nUPDATE /* inline comment */ test SET x = 1 WHERE id = 1;" + assert is_destructive(["update"], sql) is False + + def test_is_destructive_update_multiple_tables_with_where_clause(): sql = "use test;\nshow databases;\nUPDATE test, foo SET x = 1 WHERE id = 1;" assert is_destructive(["update"], sql) is True