diff --git a/src/infi/clickhouse_orm/funcs.py b/src/infi/clickhouse_orm/funcs.py index b5c9bbe..f137a45 100644 --- a/src/infi/clickhouse_orm/funcs.py +++ b/src/infi/clickhouse_orm/funcs.py @@ -294,6 +294,8 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta): return 'NULL' if isinstance(arg, QuerySet): return "(%s)" % arg + if isinstance(arg, tuple): + return '(' + comma_join(F._arg_to_sql(x) for x in arg) + ')' if is_iterable(arg): return '[' + comma_join(F._arg_to_sql(x) for x in arg) + ']' return str(arg) @@ -406,11 +408,15 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta): @staticmethod @binary_operator def _in(a, b): + if is_iterable(b) and not isinstance(b, (tuple, QuerySet)): + b = tuple(b) return F('IN', a, b) @staticmethod @binary_operator def _notIn(a, b): + if is_iterable(b) and not isinstance(b, (tuple, QuerySet)): + b = tuple(b) return F('NOT IN', a, b) # Functions for working with dates and times diff --git a/tests/test_database.py b/tests/test_database.py index 78c3fdb..2fd9864 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -33,6 +33,8 @@ class DatabaseTestCase(TestCaseWithData): self._insert_and_check(self._sample_data(), len(data), batch_size=100) def test_insert__funcs_as_default_values(self): + if self.database.server_version < (20, 1, 2, 4): + raise unittest.SkipTest('Buggy in server versions before 20.1.2.4') class TestModel(Model): a = DateTimeField(default=datetime.datetime(2020, 1, 1)) b = DateField(default=F.toDate(a)) diff --git a/tests/test_funcs.py b/tests/test_funcs.py index a2db093..06157d4 100644 --- a/tests/test_funcs.py +++ b/tests/test_funcs.py @@ -75,9 +75,11 @@ class FuncsTestCase(TestCaseWithData): self.assertEqual(F('func', F('sqrt', 25)).to_sql(), 'func(sqrt(25))') # Iterables as args x = [1, 'z', F('foo', 17)] - for y in [x, tuple(x), iter(x)]: + for y in [x, iter(x)]: self.assertEqual(F('func', y, 5).to_sql(), "func([1, 'z', foo(17)], 5)") - self.assertEqual(F('func', [(1, 2), (3, 4)]).to_sql(), "func([[1, 2], [3, 4]])") + # Tuples as args + self.assertEqual(F('func', [(1, 2), (3, 4)]).to_sql(), "func([(1, 2), (3, 4)])") + self.assertEqual(F('func', tuple(x), 5).to_sql(), "func((1, 'z', foo(17)), 5)") # Binary operator functions self.assertEqual(F.plus(1, 2).to_sql(), "(1 + 2)") self.assertEqual(F.lessOrEquals(1, 2).to_sql(), "(1 <= 2)") @@ -187,9 +189,9 @@ class FuncsTestCase(TestCaseWithData): self._test_func(one | 0, 1) self._test_func(0 | one, 1) # ^ - self._test_func(one ^ one, 0) - self._test_func(one ^ 0, 1) - self._test_func(0 ^ one, 1) + self._test_func(one ^ one) + self._test_func(one ^ 0) + self._test_func(0 ^ one) # ~ self._test_func(~one, 0) self._test_func(~~one, 1)