except TypeError:
pass
- whenlist = [
+ self.whens = [
(
coercions.expect(
roles.ExpressionElementRole,
for (c, r) in new_whens
]
- if whenlist:
- type_ = whenlist[-1][-1].type
- else:
- type_ = None
-
if value is None:
self.value = None
else:
self.value = coercions.expect(roles.ExpressionElementRole, value)
- self.type = cast(_T, type_)
- self.whens = whenlist
-
if else_ is not None:
self.else_ = coercions.expect(roles.ExpressionElementRole, else_)
else:
self.else_ = None
+ type_ = next(
+ (
+ then.type
+ # Iterate `whens` in reverse to match previous behaviour
+ # where type of final element took priority
+ for *_, then in reversed(self.whens)
+ if not then.type._isnull
+ ),
+ self.else_.type if self.else_ is not None else type_api.NULLTYPE,
+ )
+ self.type = cast(_T, type_)
+
@util.ro_non_memoized_property
def _from_objects(self) -> List[FromClause]:
return list(
from sqlalchemy import text
from sqlalchemy.sql import column
from sqlalchemy.sql import table
+from sqlalchemy.sql.sqltypes import NullType
from sqlalchemy.testing import AssertsCompiledSQL
from sqlalchemy.testing import eq_
from sqlalchemy.testing import fixtures
("two", 2),
("other", 3),
]
+
+ def test_type_of_case_expression_with_all_nulls(self):
+ expr = case(
+ (info_table.c.pk < 0, None),
+ (info_table.c.pk > 9, None),
+ )
+
+ assert isinstance(expr.type, NullType)
+
+ def test_type_of_case_expression_with_all_nulls_with_else(self):
+ expr = case(
+ (info_table.c.pk < 0, None),
+ (info_table.c.pk > 9, None),
+ else_=column("q"),
+ )
+
+ assert isinstance(expr.type, NullType)
+
+ def test_type_of_case_expression_with_null_case_and_no_else_clause(self):
+ expr = case(
+ (info_table.c.pk < 0, None),
+ # This mixing of types is not legal in most DBMSs, but we want to
+ # test that types of later cases take priority over earlier ones
+ (info_table.c.pk < 5, "five"),
+ (info_table.c.pk <= 9, info_table.c.pk),
+ (info_table.c.pk > 9, None),
+ )
+
+ assert isinstance(expr.type, Integer)
+
+ def test_type_of_case_expression_with_null_case_and_else_clause(self):
+ expr = case(
+ (info_table.c.pk < 0, None),
+ else_=info_table.c.pk,
+ )
+
+ assert isinstance(expr.type, Integer)