Fixed SQL composition bug which impacted caching where using a ``None``
value inside of an ``in_()`` expression would bypass the usual "expanded
bind parameter" logic used by the IN construct, which allows proper caching
to take place.
Fixes: #12314
References: #12312
Change-Id: I0d2fc4e15c73407379ba368dd4ee32660fc66259
(cherry picked from commit
79505b03b61f622615be2d2bc1434671c29b0cc5)
--- /dev/null
+.. change::
+ :tags: bug, sql
+ :tickets: 12314
+
+ Fixed SQL rendering bug which impacted caching where using a ``None`` value
+ inside of an ``in_()`` expression would bypass the usual "expanded bind
+ parameter" logic used by the IN construct, which allows proper caching to
+ take place.
+
else:
non_literal_expressions[o] = o
- elif o is None:
- non_literal_expressions[o] = elements.Null()
if non_literal_expressions:
return elements.ClauseList(
"check_post_param": {},
},
),
- (lambda t: t.c.foo.in_([None]), "sometable.foo IN (NULL)", {}),
+ (
+ lambda t: t.c.foo.in_([None]),
+ "sometable.foo IN (__[POSTCOMPILE_foo_1])",
+ {},
+ ),
)
def test_strict_binds(self, expr, compiled, kw):
"""test the 'strict' compiler binds."""
is_true(c1._generate_cache_key() != c3._generate_cache_key())
is_false(c1._generate_cache_key() == c3._generate_cache_key())
+ def test_in_with_none(self):
+ """test #12314"""
+
+ def fixture():
+ elements = list(
+ random_choices([1, 2, None, 3, 4], k=random.randint(1, 7))
+ )
+
+ # slight issue. if the first element is None and not an int,
+ # the type of the BindParameter goes from Integer to Nulltype.
+ # but if we set the left side to be Integer then it comes from
+ # that side, and the vast majority of in_() use cases come from
+ # a typed column expression, so this is fine
+ return (column("x", Integer).in_(elements),)
+
+ self._run_cache_key_fixture(fixture, False)
+
def test_cache_key(self):
for fixtures_, compare_values in [
(self.fixtures, True),
)
def test_in_28(self):
+ """revised to test #12314"""
self.assert_compile(
- self.table1.c.myid.in_([None]), "mytable.myid IN (NULL)"
+ self.table1.c.myid.in_([None]),
+ "mytable.myid IN (__[POSTCOMPILE_myid_1])",
+ )
+
+ @testing.combinations(
+ [1, 2, None, 3],
+ [None, None, None],
+ [None, 2, 3, 3],
+ )
+ def test_in_null_combinations(self, expr):
+ """test #12314"""
+
+ self.assert_compile(
+ self.table1.c.myid.in_(expr),
+ "mytable.myid IN (__[POSTCOMPILE_myid_1])",
)
@testing.combinations(True, False)