Skip to content

fix(mysql): strip multi trailing semicolons before LIMIT/EXPLAIN - #2475

Closed
Bartok9 wants to merge 3 commits into
Canner:mainfrom
Bartok9:fix/mysql-multi-semicolon-whitespace
Closed

fix(mysql): strip multi trailing semicolons before LIMIT/EXPLAIN#2475
Bartok9 wants to merge 3 commits into
Canner:mainfrom
Bartok9:fix/mysql-multi-semicolon-whitespace

Conversation

@Bartok9

@Bartok9 Bartok9 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace MySQL sql.rstrip().rstrip(";").rstrip() with a terminating-run regex strip before LIMIT injection and EXPLAIN.
  • Fixes SELECT 1; ; style inputs that still ended with ; and broke EXPLAIN/LIMIT rewrite.

Motivation

Chained rstrip only removes a contiguous run of ; after whitespace strip. When whitespace appears between trailing semicolons, a ; remains. Apache-2.0 path: core/wren/**.

Verification

....                                                                     [100%]
4 passed in 0.31s

Proof without the fix: "SELECT 1; ;".rstrip().rstrip(";").rstrip()'SELECT 1;'.

Duplicates

No open PR on MySQL multi-semicolon strip.

Summary by CodeRabbit

  • Bug Fixes

    • Improved MySQL/Doris SQL generation by more reliably trimming trailing semicolons, including multiple semicolons separated by whitespace.
    • LIMIT queries and EXPLAIN dry-runs now construct SQL consistently after semicolon trimming.
    • Preserves semicolons that appear inside quoted string literals.
  • Tests

    • Added unit coverage for single/double trailing semicolons, multiple trailing semicolons with interior whitespace, and semicolons inside string literals.

@github-actions github-actions Bot added python Pull requests that update Python code core labels Jul 11, 2026
@coderabbitai

coderabbitai Bot commented Jul 11, 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4bf406e2-d426-4555-9f2f-7ab1cfa67f33

📥 Commits

Reviewing files that changed from the base of the PR and between ca87818 and a0045db.

📒 Files selected for processing (2)
  • core/wren/src/wren/connector/mysql.py
  • core/wren/tests/unit/test_mysql_semicolon.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/wren/src/wren/connector/mysql.py
  • core/wren/tests/unit/test_mysql_semicolon.py

Walkthrough

The MySQL connector adds regex-based trailing-semicolon stripping for LIMIT and EXPLAIN SQL construction, with tests covering repeated semicolons, whitespace, and quoted string literals.

Changes

MySQL semicolon handling

Layer / File(s) Summary
Trailing-semicolon helper
core/wren/src/wren/connector/mysql.py
Adds a regex-based helper that removes terminating semicolons and whitespace while preserving semicolons in string literals.
SQL composition and validation
core/wren/src/wren/connector/mysql.py, core/wren/tests/unit/test_mysql_semicolon.py
Uses the helper before appending LIMIT and constructing EXPLAIN statements, with focused coverage for single, repeated, and quoted semicolons.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • Canner/WrenAI issue 2441 — Proposes consolidating MySQL semicolon-stripping behavior into a shared helper.

Possibly related PRs

  • Canner/WrenAI#2420 — Applies a similar semicolon-stripping helper during connector SQL composition.
  • Canner/WrenAI#2421 — Applies related semicolon stripping when constructing EXPLAIN statements.
  • Canner/WrenAI#2422 — Applies similar stripping before LIMIT and EXPLAIN SQL composition.

Poem

I nibbled semicolons, one by one,
Till LIMIT queries could safely run.
EXPLAIN now follows the trail,
Strings keep their marks without fail.
Hop, hop—clean SQL prevails! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 clearly matches the main change: stripping trailing semicolons before MySQL LIMIT and EXPLAIN rewrites.
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.
✨ 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.

🧹 Nitpick comments (1)
core/wren/tests/unit/test_mysql_semicolon.py (1)

15-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a test for trailing whitespace without semicolons.

The regex [;\s]+\Z strips trailing whitespace even when no semicolons are present (e.g., "SELECT 1 \n""SELECT 1"). This behavior is a side effect of the character class and isn't explicitly covered by the current tests. A one-line test would document this contract.

🧪 Suggested additional test
 def test_helper_double_semicolon():
     assert _strip_trailing_semicolon("SELECT 1;;") == "SELECT 1"
+
+
+def test_helper_strips_trailing_whitespace_without_semicolons():
+    assert _strip_trailing_semicolon("SELECT 1   \n") == "SELECT 1"
🤖 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 `@core/wren/tests/unit/test_mysql_semicolon.py` around lines 15 - 21, Add a
unit test alongside test_helper_preserves_semicolon_in_string_literal and
test_helper_double_semicolon that verifies _strip_trailing_semicolon("SELECT 1  
\n") returns "SELECT 1", documenting that trailing whitespace is removed even
without a semicolon.
🤖 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 `@core/wren/tests/unit/test_mysql_semicolon.py`:
- Around line 15-21: Add a unit test alongside
test_helper_preserves_semicolon_in_string_literal and
test_helper_double_semicolon that verifies _strip_trailing_semicolon("SELECT 1  
\n") returns "SELECT 1", documenting that trailing whitespace is removed even
without a semicolon.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aa9e9353-657f-4257-ac90-8941b6a8d3d3

📥 Commits

Reviewing files that changed from the base of the PR and between bdaefa9 and a99b269.

📒 Files selected for processing (2)
  • core/wren/src/wren/connector/mysql.py
  • core/wren/tests/unit/test_mysql_semicolon.py

@goldmedal

Copy link
Copy Markdown
Collaborator

The shared CI failure here (maturin failedcannot update the lock file core/wren-core-py/Cargo.lock because --locked was passed) came from the Rust core 0.2.0 bump in #2467 leaving core/wren-core-py/Cargo.lock out of sync. That's now fixed on main by #2478 — please rebase onto latest main to pick up the lockfile fix and turn CI green. 🙏

@Bartok9
Bartok9 force-pushed the fix/mysql-multi-semicolon-whitespace branch from 8511b08 to ca87818 Compare July 13, 2026 02:32
@Bartok9

Bartok9 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Done — rebased onto latest main to pick up the core/wren-core-py/Cargo.lock fix from #2478. CI should go green now. Thanks @goldmedal! 🙏

Bartok9 added 3 commits July 13, 2026 08:11
str.rstrip(";").rstrip() leaves a terminator when whitespace sits
between trailing semicolons (SELECT 1; ;). Use the terminating-run
regex shared with other connectors.
@Bartok9
Bartok9 force-pushed the fix/mysql-multi-semicolon-whitespace branch from ca87818 to a0045db Compare July 13, 2026 12:11
@goldmedal

Copy link
Copy Markdown
Collaborator

This overlaps with #2480 — I think we can consolidate on that one.

Both make the same functional change at the same call sites:

  • Here: adds a local regex _strip_trailing_semicolon and routes _apply_limit and the dry_run EXPLAIN through it, replacing the inline sql.rstrip().rstrip(';').rstrip() (which misses whitespace between trailing semicolons, e.g. SELECT 1; ;).
  • refactor(connector): share strip_trailing_semicolon in base #2480: routes those same two call sites (_apply_limit, dry_run EXPLAIN) through the shared strip_trailing_semicolon in connector/base.py — same [;\s]+\Z regex.

So the outcome is identical, but #2480 uses the shared helper instead of adding another per-connector copy — which is the point of the consolidation (#2441). The multi-semicolon fix from this PR is fully preserved by #2480, so nothing is lost.

Plan is to keep #2480 and close this one once it lands. Thanks for the fix — it's carried over intact.

@Bartok9

Bartok9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Sounds good — makes total sense to consolidate on #2480 via the shared strip_trailing_semicolon helper rather than keep a per-connector copy; that's exactly the intent of #2441. Glad the multi-semicolon behavior carries over intact. Happy to close this once #2480 lands, or you can close it whenever's convenient. Thanks @goldmedal! 🙏

@goldmedal

Copy link
Copy Markdown
Collaborator

@Bartok9, there are some conflicts.

@Bartok9

Bartok9 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of #2480, which landed the shared strip_trailing_semicolon helper and preserves the multi-semicolon behavior at the same MySQL call sites. Thanks @goldmedal! 🙏

@Bartok9 Bartok9 closed this Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants