sqlalchemy: Incorrect code for sa.values on SQLite and MariaDB
Describe the bug
SQLAlchemy generates incorrect SQL for Values queries on SQLite and MariaDB. The code example is for SQLite.
To Reproduce
import sqlalchemy as sa
myvalues = sa.values(sa.column('x'), name='myvalues').data([(7,)])
stmt = sa.select(myvalues)
engine = sa.create_engine("sqlite+pysqlite:///:memory:")
with engine.connect() as conn:
print(conn.execute(stmt).all())
Error
Traceback (most recent call last):
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1799, in _execute_context
self.dialect.do_execute(
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
cursor.execute(statement, parameters)
sqlite3.OperationalError: near "(": syntax error
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bugreport1.py", line 9, in <module>
print(conn.execute(stmt).all())
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1286, in execute
return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
return connection._execute_clauseelement(
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1478, in _execute_clauseelement
ret = self._execute_context(
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1842, in _execute_context
self._handle_dbapi_exception(
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2023, in _handle_dbapi_exception
util.raise_(
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1799, in _execute_context
self.dialect.do_execute(
File "/home/asbuch/lib/virtualenvs/alchemy/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) near "(": syntax error
[SQL: SELECT myvalues.x
FROM (VALUES (?)) AS myvalues (x)]
[parameters: (7,)]
(Background on this error at: https://sqlalche.me/e/14/e3q8)
Versions
- OS: Ubuntu 20.04.3
- Python: 3.8.10
- SQLAlchemy: 1.4.25
- Database: SQLite 2.6.0 and MariaDB 10.5.12
- DBAPI: sqlite3 3.31.1 and mysql-connector-python 8.0.22
Additional context
This SQL works on both SQLite and MariaDB:
select anon.x from (select 3 as x, 1 as y union all values (1,2), (3,4)) anon;
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 1
- Comments: 15 (11 by maintainers)
Apart from a UNION statement, you can also use a CTE, and include the column names in the CTE name.
The example from the report:
can be rendered as
Demo in the
sqlite3cli:You’d need
Valuesto inherit fromHasCTEto support.cte(), and an update to the SQLite compiler to use theValuesobject as a CTE with the right name and column names, of course.oh sorry! I was working on a recipe now. We probably should include this in the docs, or in the examples, or something, and maybe even have it in the test suite for now seeing that two dfiferent datbases use the same workaround. The script below runs for all three targeted DBs:
Thanks for the comments! Values can be used without typing select on both sqlite and mariadb:
I don’t know if any column names are assigned on sqlite. On MariaDB the column names appear to be the same as the values in the first row, but I don’t know if that is documented anywhere:
That is what I call a hack! 😃