diff --git a/dbms/src/Dictionaries/ComplexKeyCacheDictionary_setAttributeValue.cpp b/dbms/src/Dictionaries/ComplexKeyCacheDictionary_setAttributeValue.cpp index cf2eef82347..24b7d83f14e 100644 --- a/dbms/src/Dictionaries/ComplexKeyCacheDictionary_setAttributeValue.cpp +++ b/dbms/src/Dictionaries/ComplexKeyCacheDictionary_setAttributeValue.cpp @@ -63,9 +63,9 @@ void ComplexKeyCacheDictionary::setAttributeValue(Attribute & attribute, const s const auto str_size = string.size(); if (str_size != 0) { - auto string_ptr = string_arena->alloc(str_size + 1); - std::copy(string.data(), string.data() + str_size + 1, string_ptr); - string_ref = StringRef{string_ptr, str_size}; + auto str_ptr = string_arena->alloc(str_size); + std::copy(string.data(), string.data() + str_size, str_ptr); + string_ref = StringRef{str_ptr, str_size}; } else string_ref = {}; diff --git a/dbms/tests/integration/test_cached_dictionary_string/__init__.py b/dbms/tests/integration/test_cached_dictionary_string/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/integration/test_cached_dictionary_string/configs/config.xml b/dbms/tests/integration/test_cached_dictionary_string/configs/config.xml new file mode 100644 index 00000000000..a1518083be3 --- /dev/null +++ b/dbms/tests/integration/test_cached_dictionary_string/configs/config.xml @@ -0,0 +1,30 @@ + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + 9000 + 127.0.0.1 + + + + true + none + + AcceptCertificateHandler + + + + + 500 + 5368709120 + ./clickhouse/ + users.xml + + /etc/clickhouse-server/config.d/*.xml + diff --git a/dbms/tests/integration/test_cached_dictionary_string/configs/dictionaries/complex_key_cache_string.xml b/dbms/tests/integration/test_cached_dictionary_string/configs/dictionaries/complex_key_cache_string.xml new file mode 100644 index 00000000000..0c3ba112215 --- /dev/null +++ b/dbms/tests/integration/test_cached_dictionary_string/configs/dictionaries/complex_key_cache_string.xml @@ -0,0 +1,45 @@ + + + radars + + + localhost + 9000 + default + + default + radars_table
+
+ + + + + radar_id + String + False + False + + + + radar_ip + String + + False + True + + + client_id + String + + False + True + + + + + 20 + + + 1 +
+
diff --git a/dbms/tests/integration/test_cached_dictionary_string/configs/users.xml b/dbms/tests/integration/test_cached_dictionary_string/configs/users.xml new file mode 100644 index 00000000000..6061af8e33d --- /dev/null +++ b/dbms/tests/integration/test_cached_dictionary_string/configs/users.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + ::/0 + + default + default + + + + + + + + diff --git a/dbms/tests/integration/test_cached_dictionary_string/test.py b/dbms/tests/integration/test_cached_dictionary_string/test.py new file mode 100644 index 00000000000..f3381581121 --- /dev/null +++ b/dbms/tests/integration/test_cached_dictionary_string/test.py @@ -0,0 +1,51 @@ +import pytest +import os +import time +from helpers.cluster import ClickHouseCluster +import random + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +cluster = ClickHouseCluster(__file__, base_configs_dir=os.path.join(SCRIPT_DIR, 'configs')) + +node = cluster.add_instance('node', main_configs=['configs/dictionaries/complex_key_cache_string.xml']) + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + node.query("create table radars_table (radar_id String, radar_ip String, client_id String) engine=MergeTree() order by radar_id") + + yield cluster + finally: + cluster.shutdown() + + +def test_memory_consumption(started_cluster): + node.query("insert into radars_table select toString(rand() % 5000), '{0}', '{0}' from numbers(1000)".format('w' * 8)) + node.query("insert into radars_table select toString(rand() % 5000), '{0}', '{0}' from numbers(1000)".format('x' * 16)) + node.query("insert into radars_table select toString(rand() % 5000), '{0}', '{0}' from numbers(1000)".format('y' * 32)) + node.query("insert into radars_table select toString(rand() % 5000), '{0}', '{0}' from numbers(1000)".format('z' * 64)) + + # Fill dictionary + node.query("select dictGetString('radars', 'client_id', tuple(toString(number))) from numbers(0, 5000)") + + allocated_first = int(node.query("select bytes_allocated from system.dictionaries where name = 'radars'").strip()) + + alloc_array = [] + for i in xrange(5): + node.query("select dictGetString('radars', 'client_id', tuple(toString(number))) from numbers(0, 5000)") + + allocated = int(node.query("select bytes_allocated from system.dictionaries where name = 'radars'").strip()) + alloc_array.append(allocated) + + # size doesn't grow + assert all(allocated_first >= a for a in alloc_array) + + for i in xrange(5): + node.query("select dictGetString('radars', 'client_id', tuple(toString(number))) from numbers(0, 5000)") + + allocated = int(node.query("select bytes_allocated from system.dictionaries where name = 'radars'").strip()) + alloc_array.append(allocated) + + # size doesn't grow + assert all(allocated_first >= a for a in alloc_array)