Skip to content

BUG: Executing SQL containing non-escaped percent sign fails without parameters #34211

Closed
@john-bodley

Description

@john-bodley
  • I have checked that this issue has not already been reported.

  • I have confirmed this bug exists on the latest version of pandas.

  • (optional) I have confirmed this bug exists on the master branch of pandas.


Note: Please read this guide detailing how to provide the necessary information for us to reproduce your bug.

Code Sample, a copy-pastable example

import pandas as pd 

pd.read_sql("SELECT 100 AS '100%'", con="mysql://root@localhost:3306") 

raises the follow exception:

ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not enough arguments for format string

Problem description

Many DB-APIs (MySQL, PyHive, etc.) when executing a statement explicitly check whether the optional parameters are/are not explicitly None (as opposed to falsy) prior to substitution. The SQL statements in Pandas are executed via the SQLAlchemy connection (per here) resulting in parameters of type NoneType being translated into an empty dictionary which can be problematic for the checks.

Many of these DB-APIs use the % operator for applying the parameters which is problematic if no parameters are specified and the SQL statement contains the % character (common in LIKE operator). One could modify their SQL by escaping the % percent character however the preferred fix is merely to leverage SQLAlchemy's execution_options setting no_parameters=True per,

no_parameters – When True, if the final parameter list or dictionary is totally empty, will invoke the statement on the cursor as cursor.execute(statement), not passing the parameter collection at all. Some DBAPIs such as psycopg2 and mysql-python consider percent signs as significant only when parameters are present; this option allows code to generate SQL containing percent signs (and possibly other characters) that is neutral regarding whether it’s executed by the DBAPI or piped into a script that’s later invoked by command line tools.

which ensures that falsy parameters will not pass the parameters to the DB-API resulting in parameters being None and thus no parameter formatting will be attempted.

Expected Output

   100%
0   100

Output of pd.show_versions()

[paste the output of pd.show_versions() here leaving a blank line after the details tag]

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugIO SQLto_sql, read_sql, read_sql_query

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions