-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Summary
When a column is named after a SQL reserved word (e.g. table), SQLAlchemy's auto-quoting mechanism (quote=None, the default) wraps it in double quotes. Because ibm_db_sa provides the name in lowercase, the generated SQL contains "table" (lowercase, quoted). DB2 treats quoted identifiers as case-sensitive, but stores unquoted identifiers as UPPERCASE in the catalog. This mismatch causes SQL0206N:
sqlalchemy.exc.ProgrammingError: ibm_db_dbi::ProgrammingError: Binding Error:
[IBM][CLI Driver][DB2/LINUXX8664] SQL0206N "FE_CODETABLE_1.table" is not valid
in the context where it is used. SQLSTATE=42703 SQLCODE=-206
The same column works fine when accessed unquoted (quote=False), because DB2 folds it to TABLE automatically.
Environment
- SQLAlchemy: 2.0.46
- ibm_db_sa: 0.4.3
- Database: IBM DB2 for Linux (DB2/LINUXX8664)
Steps to reproduce
import sqlalchemy as sa
metadata = sa.MetaData()
# Column named "table" — a SQL reserved word.
# quote is omitted, so SQLAlchemy should auto-detect and handle it.
codetable = sa.Table(
"fe_codetable",
metadata,
sa.Column("oid", sa.BigInteger(), primary_key=True),
sa.Column("table", sa.String()),
)
alias = codetable.alias()
stmt = sa.select(alias.c.table).where(alias.c.table == "SomeValue")
with engine.connect() as conn:
conn.execute(stmt) # → SQL0206NSetting quote=True explicitly produces the same error, because the generated SQL is identical.
Generated SQL
Both quote=None (auto) and quote=True produce:
SELECT fe_codetable_1."table"
FROM fe_codetable AS fe_codetable_1
WHERE fe_codetable_1."table" = ?DB2 sees "table" (lowercase, case-sensitive) and looks for a column literally named table. The catalog stores it as TABLE (uppercase), so the lookup fails.
Setting quote=False produces working SQL:
SELECT fe_codetable_1.table
FROM fe_codetable AS fe_codetable_1
WHERE fe_codetable_1.table = ?DB2 folds the unquoted table to TABLE, matches the catalog, and the query succeeds.