Skip to content

BUG: fix read_sql delegation for queries without select statement (GH7324) #7326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/source/v0.14.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,6 @@ Bug Fixes
- Bug in ``MultiIndex.append``, ``concat`` and ``pivot_table`` don't preserve timezone (:issue:`6606`)
- Bug in ``.loc`` with a list of indexers on a single-multi index level (that is not nested) (:issue:`7349`)
- Bug in ``Series.map`` when mapping a dict with tuple keys of different lengths (:issue:`7333`)
- Bug all ``StringMethods`` now work on empty Series (:issue:`7242`)
- Fix delegation of `read_sql` to `read_sql_query` when query does not contain
'select' (:issue:`7324`).
21 changes: 7 additions & 14 deletions pandas/io/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,26 +374,19 @@ def read_sql(sql, con, index_col=None, coerce_float=True, params=None,
"""
pandas_sql = pandasSQL_builder(con)

if 'select' in sql.lower():
try:
if pandas_sql.has_table(sql):
return pandas_sql.read_table(
sql, index_col=index_col, coerce_float=coerce_float,
parse_dates=parse_dates, columns=columns)
except:
pass

if isinstance(pandas_sql, PandasSQLLegacy):
return pandas_sql.read_sql(
sql, index_col=index_col, params=params,
coerce_float=coerce_float, parse_dates=parse_dates)
else:
if isinstance(pandas_sql, PandasSQLLegacy):
raise ValueError("Reading a table with read_sql is not supported "
"for a DBAPI2 connection. Use an SQLAlchemy "
"engine or specify an sql query")

if pandas_sql.has_table(sql):
return pandas_sql.read_table(
sql, index_col=index_col, coerce_float=coerce_float,
parse_dates=parse_dates, columns=columns)
else:
return pandas_sql.read_sql(
sql, index_col=index_col, params=params,
coerce_float=coerce_float, parse_dates=parse_dates)


def to_sql(frame, name, con, flavor='sqlite', if_exists='fail', index=True,
Expand Down
32 changes: 31 additions & 1 deletion pandas/io/tests/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ def test_read_sql_delegate(self):
"read_sql and read_sql_query have not the same"
" result with a query")

self.assertRaises(ValueError, sql.read_sql, 'iris', self.conn)
self.assertRaises(sql.DatabaseError, sql.read_sql, 'iris', self.conn)

def test_safe_names_warning(self):
# GH 6798
Expand Down Expand Up @@ -1078,6 +1078,36 @@ def test_default_type_conversion(self):
self.assertTrue(issubclass(df.BoolColWithNull.dtype.type, np.floating),
"BoolColWithNull loaded with incorrect type")

def test_read_procedure(self):
# see GH7324. Although it is more an api test, it is added to the
# mysql tests as sqlite does not have stored procedures
df = DataFrame({'a': [1, 2, 3], 'b':[0.1, 0.2, 0.3]})
df.to_sql('test_procedure', self.conn, index=False)

proc = """DROP PROCEDURE IF EXISTS get_testdb;

CREATE PROCEDURE get_testdb ()

BEGIN
SELECT * FROM test_procedure;
END"""

connection = self.conn.connect()
trans = connection.begin()
try:
r1 = connection.execute(proc)
trans.commit()
except:
trans.rollback()
raise

res1 = sql.read_sql_query("CALL get_testdb();", self.conn)
tm.assert_frame_equal(df, res1)

# test delegation to read_sql_query
res2 = sql.read_sql("CALL get_testdb();", self.conn)
tm.assert_frame_equal(df, res2)


class TestPostgreSQLAlchemy(_TestSQLAlchemy):
"""
Expand Down