Skip to content

Conversation

@SergioGarcia00
Copy link

@SergioGarcia00 SergioGarcia00 commented Oct 4, 2025

The issue is coming from #35484

What does this PR do?
Fixes a long-standing issue where pd.read_sql fails to handle the percent character (%) when using SQLAlchemy engines.
Since pandas ≥ 1.1, the IO layer sets no_parameters=True for SQL execution, which causes plain string queries containing % to be misinterpreted as parameter placeholders.

As a result:
Queries like SELECT 1 % 2 raised UndefinedFunction errors.
Queries using LIKE 'Jo%' failed to match rows correctly.
This PR introduces a small helper _sa_text_if_string that wraps plain SQL strings in sqlalchemy.text() before execution.
This ensures that % is treated correctly, while SQLAlchemy select() objects continue to work as before.

Summary of changes
pandas/io/sql.py
Added _sa_text_if_string(stmt) helper.
Applied it inside SQLDatabase.read_query() before self.execute().
pandas/tests/io/sql/test_percent_patterns.py

Added new tests for:
SELECT 5 % 2 (modulo operator)
LIKE 'John%' (pattern matching)
SQLAlchemy selectable using (literal(7) % literal(3))

Other
Restored .gitignore to match upstream so only relevant files are modified.

How was this tested?
All pre-commit checks (ruff, codespell, etc.) pass locally.
pytest -q pandas/tests/io/sql/test_percent_patterns.py -ra → 3 tests passed.
Tested both on in-memory SQLite and PostgreSQL (PANDAS_TEST_POSTGRES_URI).

Notes for reviewers
The change only affects plain string queries.
SQLAlchemy expressions (select(), text(), etc.) remain unaffected.
A short “Bug Fixes” note will be added to doc/source/whatsnew/v3.x.y.rst.

@Alvaro-Kothe
Copy link
Member

@SergioGarcia00 Can you update the description linking to the relevant issue?

@SergioGarcia00
Copy link
Author

SergioGarcia00 commented Oct 4, 2025

@SergioGarcia00 Can you update the description linking to the relevant issue?

Oh, missed that sry. #35484

@SergioGarcia00
Copy link
Author

SergioGarcia00 commented Oct 7, 2025

I dont really understand the errors I got by the CI, is there something I did wrong?

Added type hints for function signatures and improved code clarity.
Updated the _sa_text_if_string function to include type hints and enhanced docstring for clarity. Modified the read_sql function to use the updated _sa_text_if_string function.
Refactor SQL tests to use SQLAlchemy select statements and remove unused imports.
@SergioGarcia00
Copy link
Author

I really dont get it,
What am I doing wrong?

Reorder imports and clean up comments in test file.
@SergioGarcia00
Copy link
Author

pre-commit.ci autofix

@SergioGarcia00 SergioGarcia00 marked this pull request as draft November 17, 2025 08:58
@SergioGarcia00 SergioGarcia00 marked this pull request as ready for review November 17, 2025 09:04
@SergioGarcia00
Copy link
Author

It looks like the failing job is due to an artifact/cache conflict (Failed to CreateArtifact: 409 Conflict), not the code itself. Could someone with permissions re-run the “Without PyArrow” job?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants