diff --git a/clickhouse_driver/settings/types.py b/clickhouse_driver/settings/types.py index 922cad3a..2d824343 100644 --- a/clickhouse_driver/settings/types.py +++ b/clickhouse_driver/settings/types.py @@ -6,41 +6,36 @@ class SettingType(object): @classmethod def write(cls, value, buf): - cls.write_value(value, buf) - - @classmethod - def write_value(cls, value, buf): raise NotImplementedError class SettingUInt64(SettingType): @classmethod - def write_value(cls, value, buf): + def write(cls, value, buf): write_varint(int(value), buf) class SettingBool(SettingType): @classmethod - def write_value(cls, value, buf): - value = asbool(value) - write_varint(value, buf) + def write(cls, value, buf): + write_varint(asbool(value), buf) class SettingString(SettingType): @classmethod - def write_value(cls, value, buf): + def write(cls, value, buf): write_binary_str(value, buf) class SettingChar(SettingType): @classmethod - def write_value(cls, value, buf): + def write(cls, value, buf): write_binary_str(value[0], buf) class SettingFloat(SettingType): @classmethod - def write_value(cls, value, buf): + def write(cls, value, buf): """ Float is written in string representation. """ @@ -49,7 +44,7 @@ def write_value(cls, value, buf): class SettingMaxThreads(SettingUInt64): @classmethod - def write_value(cls, value, buf): + def write(cls, value, buf): if value == 'auto': value = 0 - super(SettingMaxThreads, cls).write_value(value, buf) + super(SettingMaxThreads, cls).write(value, buf) diff --git a/clickhouse_driver/settings/writer.py b/clickhouse_driver/settings/writer.py index 834ef8d0..7565eb61 100644 --- a/clickhouse_driver/settings/writer.py +++ b/clickhouse_driver/settings/writer.py @@ -8,22 +8,24 @@ def write_settings(settings, buf, settings_as_strings): + is_important = 0 + for setting, value in (settings or {}).items(): # If the server support settings as string we do not need to know # anything about them, so we can write any setting. if settings_as_strings: write_binary_str(setting, buf) - write_binary_uint8(0, buf) + write_binary_uint8(is_important, buf) write_binary_str(str(value), buf) - continue - - # If the server requires string in binary, then they cannot be written - # without type. - setting_writer = available_settings.get(setting) - if not setting_writer: - logger.warning('Unknown setting %s. Type is unknown. Skipping', setting) - continue - write_binary_str(setting, buf) - setting_writer.write(value, buf) + + else: + # If the server requires string in binary, + # then they cannot be written without type. + setting_writer = available_settings.get(setting) + if not setting_writer: + logger.warning('Unknown setting %s. Skipping', setting) + continue + write_binary_str(setting, buf) + setting_writer.write(value, buf) write_binary_str('', buf) # end of settings diff --git a/docs/misc.rst b/docs/misc.rst index 05dc5856..789bd385 100644 --- a/docs/misc.rst +++ b/docs/misc.rst @@ -111,3 +111,15 @@ corresponding setting type from package or write your own type. >>> client = Client('localhost', settings={'allow_suspicious_low_cardinality_types': True}) >>> client.execute('CREATE TABLE test (x LowCardinality(Int32)) Engine = Null') [] + + +*New in version 0.1.5.* + +Modern ClickHouse servers (20.*+) use text serialization for settings instead of +binary serialization. You don't have to add missed settings manually into +available. Just specify new settings and it will work. + + .. code-block:: python + + >>> client = Client('localhost', settings={'brand_new_setting': 42}) + >>> client.execute('SELECT 1') diff --git a/tests/test_settings.py b/tests/test_settings.py index 8a294ed4..507a8cb0 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -2,6 +2,7 @@ from tests.testcase import BaseTestCase from tests.util import require_server_version + class SettingTestCase(BaseTestCase): def test_int_apply(self): settings = {'max_query_size': 142}