Skip to content

fix(mysql): handle brackets in connection URLs#2367

Open
OmarAhmed-A wants to merge 1 commit into
Canner:mainfrom
OmarAhmed-A:fix/mysql-connection-url-brackets
Open

fix(mysql): handle brackets in connection URLs#2367
OmarAhmed-A wants to merge 1 commit into
Canner:mainfrom
OmarAhmed-A:fix/mysql-connection-url-brackets

Conversation

@OmarAhmed-A

@OmarAhmed-A OmarAhmed-A commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix MySQL connectionUrl parsing when the password contains raw [ or ].

Before this change, URL-based MySQL connections could fail during parsing with an invalid IPv6 URL error because urllib.parse.urlparse() treated brackets in the password as host
delimiters.

Root cause

The MySQL connector passed the raw connection URL directly to urlparse(). A URL like:

mysql://user:p[a]ss@host:3306/db

fails before any connection attempt because urlparse() interprets [ / ] in the netloc as IPv6 syntax.

There was also an adjacent decoding issue: MySQL URL userinfo was decoded with unquote_plus, which incorrectly turns literal + into a space.

Changes

  • add a MySQL-specific URL parse helper that percent-encodes raw [ / ] in userinfo before calling urlparse()

  • only sanitize the userinfo segment, so valid IPv6 hosts like [::1] still parse correctly

  • switch MySQL URL decoding from unquote_plus to unquote for:

    • username
    • password
    • database path
  • keep existing scheme validation and kwarg precedence unchanged

Tests

Added unit coverage for:

  • raw bracketed passwords in MySQL URLs
  • all supported MySQL URL schemes
  • percent-decoding of username, password, and database name
  • preserving literal + in userinfo
  • preserving valid IPv6 host parsing
  • kwargs overriding query-string params
  • invalid scheme raising INVALID_CONNECTION_INFO

Issue

Closes #459

Summary by CodeRabbit

  • Bug Fixes

    • Fixed MySQL connection URL parsing to correctly handle special characters and encoded components in credentials; improved IPv6 address support.
  • Tests

    • Added comprehensive test coverage for MySQL connection URL parsing with various credential formats and edge cases.

Copilot AI review requested due to automatic review settings June 12, 2026 12:23
@github-actions github-actions Bot added python Pull requests that update Python code core labels Jun 12, 2026
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: aef18e49-8293-41f1-a732-25e4efdbe55b

📥 Commits

Reviewing files that changed from the base of the PR and between 6e150e2 and bd594db.

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

Walkthrough

This PR fixes bracket character handling in MySQL connection URLs. A new _parse_mysql_connection_url() function sanitizes brackets within userinfo before parsing, allowing raw credentials with [ or ] to coexist with IPv6 host syntax. Credentials are now decoded using unquote instead of unquote_plus. Comprehensive unit tests validate bracket preservation, percent-decoding, IPv6 parsing, and invalid scheme rejection.

Changes

MySQL URL credential parsing with bracket safety

Layer / File(s) Summary
URL parsing and credential extraction
core/wren/src/wren/connector/mysql.py
New _parse_mysql_connection_url() escapes brackets in userinfo before calling urlparse. _build_mysql_connect_kwargs() is updated to parse through this sanitized path, decode user/passwd/db using unquote, and preserve existing scheme validation and host normalization.
URL parsing test coverage
core/wren/tests/unit/test_mysql_helpers.py
Test helper classes _FakeConnUrl and _FakeConnInfoFromUrl provide controlled URL inputs. Six new tests validate bracket passwords, percent-encoded credentials, literal + in userinfo, IPv6 hosts, query parameter overrides, and invalid scheme rejection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A bracket in thy password? Fear not the IPv6 parse!
Our MySQL url now dances 'round the userinfo stars,
Escaping brackets safe, unquoting all the rest—
Raw credentials shine, no longer IPv6's jest!
The tests confirm each edge case, IPv6 hosts, and plus,
All flow through unscrambled now, without the fuss! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% 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 PR title 'fix(mysql): handle brackets in connection URLs' accurately describes the main change: fixing MySQL URL parsing to handle brackets in connection URLs.
Linked Issues check ✅ Passed The PR fully addresses issue #459 by implementing URL parsing that handles raw brackets in passwords, switching to unquote for proper decoding, and validating with comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing MySQL URL parsing to handle brackets in credentials. No unrelated modifications detected.

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

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds safer MySQL connection URL parsing to support raw [/] in credentials (without breaking IPv6 hosts), and expands unit coverage for URL decoding/override behavior.

Changes:

  • Introduces _parse_mysql_connection_url() to escape brackets in userinfo before parsing.
  • Updates _build_mysql_connect_kwargs() to use the new parser and unquote decoding.
  • Adds unit tests covering bracketed passwords, percent-decoding, literal +, IPv6, kwargs overrides, and invalid schemes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
core/wren/src/wren/connector/mysql.py Adds URL pre-sanitization and updates connect-kwargs parsing/decoding to handle bracketed credentials safely.
core/wren/tests/unit/test_mysql_helpers.py Adds unit tests validating MySQL URL parsing edge cases and error behavior.
Comments suppressed due to low confidence (1)

core/wren/src/wren/connector/mysql.py:506

  • The error message is inaccurate: the code allows mysql+pymysql and mysql+mysqldb in addition to mysql. Update the message to list the supported schemes (or say “must use a MySQL scheme: mysql, mysql+pymysql, mysql+mysqldb”) to avoid misleading users.
        if parsed.scheme not in {"mysql", "mysql+pymysql", "mysql+mysqldb"}:
            raise WrenError(
                ErrorCode.INVALID_CONNECTION_INFO,
                "MySQL connection URL must use mysql:// scheme",
            )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 516 to +520
out: dict = {
"host": host,
"port": int(parsed.port) if parsed.port else 3306,
"user": parsed.username,
"passwd": unquote_plus(parsed.password) if parsed.password else "",
"db": parsed.path.lstrip("/") if parsed.path else None,
"user": unquote(parsed.username) if parsed.username else None,
"passwd": unquote(parsed.password) if parsed.password else "",
# ---------------------------------------------------------------------------


def _parse_mysql_connection_url(url: str):
Comment on lines +38 to +41
class _FakeConnInfoFromUrl:
def __init__(self, url: str, kwargs: dict[str, str] | None = None) -> None:
self.connection_url = _FakeConnUrl(url)
self.kwargs = kwargs
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.

Invalid IPv6 URL issue when connecting mysql

2 participants