Fix sql.false()/sql.true() rendering under use_native_boolean=False#656
Fix sql.false()/sql.true() rendering under use_native_boolean=False#656antonioyanez wants to merge 1 commit into
Conversation
HANAStatementCompiler.visit_is_true_unary_operator and visit_is_false_unary_operator unconditionally emitted `... = TRUE` / `... = FALSE`. With use_native_boolean=False, SQLAlchemy's base visit_true/visit_false renders the wrapped element as an INT literal (1/0), so a WHERE became e.g. `WHERE 0 = TRUE` — which HANA rejects with error 266 "BOOLEAN type is not comparable with INT". Branch on self.dialect.supports_native_boolean and fall back to an INT compare in non-native mode. Native-mode behaviour is unchanged.
|
|
|
Thanks for the PR. Please have a look at the failing tests and checks |
|
Heads up — CI failed on this PR at the checkout step, before any of the fix code was executed. Every job (matrix tests, pre-commit, coverage) errored with:
This is Since the workflow used for
(Switching the trigger to Happy to open a follow-up PR against |
|
Fix #662 |
|
Fixed, please try again |
| # SELECT 1 FROM DUMMY WHERE FALSE | ||
| # When the dialect is configured with ``use_native_boolean=False`` (schemas | ||
| # that store booleans as integer/tinyint), ``sql.true()``/``sql.false()`` | ||
| # render as ``1``/``0``; comparing those to the boolean literals ``TRUE``/ |
There was a problem hiding this comment.
Within comments, rst formatting (double packticks) are not needed
Summary
HANAStatementCompiler.visit_is_true_unary_operatorandvisit_is_false_unary_operatorunconditionally emit... = TRUE/... = FALSE. When the dialect is configured withuse_native_boolean=False, SQLAlchemy's basevisit_true/visit_falserender the wrapped element as an INT literal (
1/0), so the compiledWHERE becomes e.g.
WHERE 0 = TRUE— which HANA rejects with error266 "BOOLEAN type is not comparable with INT".
This PR makes both overrides branch on
self.dialect.supports_native_booleanand fall back to an INT comparein non-native mode. Native-mode behaviour is unchanged: the existing
= TRUE/= FALSEpath is preserved, which is why these overridesexist in the first place (HANA rejects a bare
WHERE TRUE/WHERE FALSE, per the comment above the methods).Reproducer
Before / After
select(literal_column("id")).where(sql.false())withuse_native_boolean=False:WHERE 0 = TRUEWHERE 0 = 1Same statement with
use_native_boolean=True(unchanged):WHERE false = TRUEWHERE false = TRUETest evidence
Added
test_sql_unary_boolean_non_nativeintest/test_sql_compile.pythat instantiates the dialect with
use_native_boolean=Falseandasserts:
where(sql.false())compiles toWHERE 0 = 1where(sql.true())compiles toWHERE 1 = 1where(and_(sql.false(), other_clause))compiles toWHERE 0 = 1(SQLAlchemy short-circuits
and_(false, ...)to justfalse, andthe resulting predicate is safe on HANA)
Verified locally that without this patch the same test asserts
WHERE 0 = TRUE(which reproduces the runtime failure), and withthe patch it asserts the safe INT compare. Existing
test_sql_unary_boolean(native-mode) still passes unchanged.Motivation
Discovered while running SQLAlchemy against a HANA schema that stores
booleans as
INTEGERfor legacy reasons (use_native_boolean=False).Any query construct that produced
sql.false()/sql.true()— whichSQLAlchemy emits under a number of internal shortcuts — hit error 266
at execution time, requiring a local workaround. This PR removes the
need for that workaround.
Files changed
sqlalchemy_hana/dialect.py— the two-method patch.test/test_sql_compile.py— regression test.CHANGES.rst— 4.6.1 entry underFixes.