# Path: src/infi/clickhouse_orm/utils.py
# def comma_join(items, stringify=False):
#     """
#     Joins an iterable of strings with commas.
#     """
#     if stringify:
#         return ', '.join(str(item) for item in items)
#     else:
#         return ', '.join(items)
# 
# def string_or_func(obj):
#     return obj.to_sql() if hasattr(obj, 'to_sql') else obj
# 
# def arg_to_sql(arg):
#     """
#     Converts a function argument to SQL string according to its type.
#     Supports functions, model fields, strings, dates, datetimes, timedeltas, booleans,
#     None, numbers, timezones, arrays/iterables.
#     """
#     from infi.clickhouse_orm import Field, StringField, DateTimeField, DateField, F, QuerySet
#     if isinstance(arg, F):
#         return arg.to_sql()
#     if isinstance(arg, Field):
#         return "`%s`" % arg
#     if isinstance(arg, str):
#         return StringField().to_db_string(arg)
#     if isinstance(arg, datetime):
#         return "toDateTime(%s)" % DateTimeField().to_db_string(arg)
#     if isinstance(arg, date):
#         return "toDate('%s')" % arg.isoformat()
#     if isinstance(arg, timedelta):
#         return "toIntervalSecond(%d)" % int(arg.total_seconds())
#     if isinstance(arg, bool):
#         return str(int(arg))
#     if isinstance(arg, tzinfo):
#         return StringField().to_db_string(arg.tzname(None))
#     if arg is None:
#         return 'NULL'
#     if isinstance(arg, QuerySet):
#         return "(%s)" % arg
#     if isinstance(arg, tuple):
#         return '(' + comma_join(arg_to_sql(x) for x in arg) + ')'
#     if is_iterable(arg):
#         return '[' + comma_join(arg_to_sql(x) for x in arg) + ']'
#     return str(arg)


import pytz
from copy import copy, deepcopy
from math import ceil
from datetime import date, datetime
from .utils import comma_join, string_or_func, arg_to_sql
        from infi.clickhouse_orm.funcs import F
        from .funcs import F
        from .database import Page
        from .engines import CollapsingMergeTree, ReplacingMergeTree
    """

    def __init__(self, sql_operator, sql_for_null=None):
        self._sql_operator = sql_operator
        self._sql_for_null = sql_for_null

    def to_sql(self, model_cls, field_name, value):
        field = getattr(model_cls, field_name)
        value = self._value_to_sql(field, value)
        if value == '\\N' and self._sql_for_null is not None:
            return ' '.join([field_name, self._sql_for_null])
        return ' '.join([field_name, self._sql_operator, value])


class InOperator(Operator):
    """
    An operator that implements IN.
    Accepts 3 different types of values:
    - a list or tuple of simple values
    - a string (used verbatim as the contents of the parenthesis)
    - a queryset (subquery)
    """

    def to_sql(self, model_cls, field_name, value):
        field = getattr(model_cls, field_name)
        if isinstance(value, QuerySet):
            value = value.as_sql()
        elif isinstance(value, str):
            pass
        else:

# Path: src/infi/clickhouse_orm/utils.py
# def comma_join(items, stringify=False):
#     """
#     Joins an iterable of strings with commas.
#     """
#     if stringify:
#         return ', '.join(str(item) for item in items)
#     else:
#         return ', '.join(items)
# 
# def string_or_func(obj):
#     return obj.to_sql() if hasattr(obj, 'to_sql') else obj
# 
# def arg_to_sql(arg):
#     """
#     Converts a function argument to SQL string according to its type.
#     Supports functions, model fields, strings, dates, datetimes, timedeltas, booleans,
#     None, numbers, timezones, arrays/iterables.
#     """
#     from infi.clickhouse_orm import Field, StringField, DateTimeField, DateField, F, QuerySet
#     if isinstance(arg, F):
#         return arg.to_sql()
#     if isinstance(arg, Field):
#         return "`%s`" % arg
#     if isinstance(arg, str):
#         return StringField().to_db_string(arg)
#     if isinstance(arg, datetime):
#         return "toDateTime(%s)" % DateTimeField().to_db_string(arg)
#     if isinstance(arg, date):
#         return "toDate('%s')" % arg.isoformat()
#     if isinstance(arg, timedelta):
#         return "toIntervalSecond(%d)" % int(arg.total_seconds())
#     if isinstance(arg, bool):
#         return str(int(arg))
#     if isinstance(arg, tzinfo):
#         return StringField().to_db_string(arg.tzname(None))
#     if arg is None:
#         return 'NULL'
#     if isinstance(arg, QuerySet):
#         return "(%s)" % arg
#     if isinstance(arg, tuple):
#         return '(' + comma_join(arg_to_sql(x) for x in arg) + ')'
#     if is_iterable(arg):
#         return '[' + comma_join(arg_to_sql(x) for x in arg) + ']'
#     return str(arg)


# Path: src/infi/clickhouse_orm/query.py
import pytz
from copy import copy, deepcopy
from math import ceil
from datetime import date, datetime
from .utils import comma_join, string_or_func, arg_to_sql
        from infi.clickhouse_orm.funcs import F
        from .funcs import F
        from .database import Page
        from .engines import CollapsingMergeTree, ReplacingMergeTree

    """

    def __init__(self, sql_operator, sql_for_null=None):
        self._sql_operator = sql_operator
        self._sql_for_null = sql_for_null

    def to_sql(self, model_cls, field_name, value):
        field = getattr(model_cls, field_name)
        value = self._value_to_sql(field, value)
        if value == '\\N' and self._sql_for_null is not None:
            return ' '.join([field_name, self._sql_for_null])
        return ' '.join([field_name, self._sql_operator, value])


class InOperator(Operator):
    """
    An operator that implements IN.
    Accepts 3 different types of values:
    - a list or tuple of simple values
    - a string (used verbatim as the contents of the parenthesis)
    - a queryset (subquery)
    """

    def to_sql(self, model_cls, field_name, value):
        field = getattr(model_cls, field_name)
        if isinstance(value, QuerySet):
            value = value.as_sql()
        elif isinstance(value, str):
            pass
        else:

            value = comma_join([self._value_to_sql(field, v) for v in value])