While reading SQLite tables using pandas and dask, I came across some unexpected behavior of SQLAlchemy when selecting from SQLite tables with datetimes (ISO formatted strings) stored as NUMERIC data type. An SQLAlchemy raw SQL query works fine, but a query using a selectable constructed from reflection fails. The two queries appear to be equivalent.
I have pasted an example below, along with the traceback. Can someone explain what is wrong with the third query in the example?
Set up table with NUMERIC datetime:
import sqlalchemy as sa
from sqlalchemy import text
connString = "sqlite:///c:\\temp\\test.db"
engine = sa.create_engine(connString)
conn = engine.connect()
conn.execute("create table testtable (uid INTEGER Primary Key, datetime NUMERIC)")
conn.execute("insert into testtable values (1, '2017-08-03 01:11:31')")
print(conn.execute('PRAGMA table_info(testtable)').fetchall())
# [(0, 'uid', 'INTEGER', 0, None, 1), (1, 'datetime', 'NUMERIC', 0, None, 0)]
Query with raw SQL works:
resultList1 = conn.execute("SELECT testtable.uid, testtable.datetime \nFROM testtable").fetchall()
print(resultList1)
# [(1, '2017-08-03 01:11:31')]
Query with this selectable works:
resultList2 = conn.execute(sa.sql.select(columns=[text('uid'),text('datetime')]).select_from(text('testtable'))).fetchall()
print(resultList2)
# [(1, '2017-08-03 01:11:31')]
Query with this selectable fails:
m = sa.MetaData()
table = sa.Table('testtable', m, autoload=True, autoload_with=engine)
selectble = sa.sql.select(table.columns).select_from(table)
print(selectble.compile().string)
# note: same raw sql query as above
# "SELECT testtable.uid, testtable.datetime \nFROM testtable"
resultList3 = conn.execute(sa.sql.select(table.columns).select_from(table)).fetchall()
# SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively...
print(resultList3)
conn.close()
The error:
Traceback (most recent call last):
File "<ipython-input-20-188c84a35d95>", line 1, in <module>
print(resultList3)
File "c:\program files\python36\lib\site-packages\sqlalchemy\engine\result.py", line 156, in __repr__
return repr(sql_util._repr_row(self))
File "c:\program files\python36\lib\site-packages\sqlalchemy\sql\util.py", line 329, in __repr__
", ".join(trunc(value) for value in self.row),
TypeError: must be real number, not str