mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 10:02:01 +00:00
Merge pull request #209 from proller/move-autotest-external-dictionaries
import autotest-external-dictionaries
This commit is contained in:
commit
909f14a063
60
dbms/tests/external_dictionaries/.gitignore
vendored
Normal file
60
dbms/tests/external_dictionaries/.gitignore
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
*-preprocessed.xml
|
||||
.idea/
|
2
dbms/tests/external_dictionaries/README.md
Normal file
2
dbms/tests/external_dictionaries/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# autotest-external-dictionaries
|
||||
Automatic tests for external dictionaries
|
1
dbms/tests/external_dictionaries/clickhouse/.gitignore
vendored
Normal file
1
dbms/tests/external_dictionaries/clickhouse/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
status
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
{"yandex":{"DateTime_%2Ebin":{"size":"43"},"Date_%2Ebin":{"size":"34"},"Float32_%2Ebin":{"size":"40"},"Float64_%2Ebin":{"size":"45"},"Int16_%2Ebin":{"size":"34"},"Int32_%2Ebin":{"size":"43"},"Int64_%2Ebin":{"size":"59"},"Int8_%2Ebin":{"size":"30"},"Parent%2Ebin":{"size":"42"},"String_%2Ebin":{"size":"109"},"UInt16_%2Ebin":{"size":"34"},"UInt32_%2Ebin":{"size":"43"},"UInt64_%2Ebin":{"size":"58"},"UInt8_%2Ebin":{"size":"30"},"__marks%2Emrk":{"size":"288"},"id%2Ebin":{"size":"46"},"key0%2Ebin":{"size":"30"},"key0_str%2Ebin":{"size":"34"},"key1%2Ebin":{"size":"30"}}}
|
@ -0,0 +1,21 @@
|
||||
ATTACH TABLE dictionary_source
|
||||
(
|
||||
id UInt64,
|
||||
key0 UInt8,
|
||||
key0_str String,
|
||||
key1 UInt8,
|
||||
UInt8_ UInt8,
|
||||
UInt16_ UInt16,
|
||||
UInt32_ UInt32,
|
||||
UInt64_ UInt64,
|
||||
Int8_ Int8,
|
||||
Int16_ Int16,
|
||||
Int32_ Int32,
|
||||
Int64_ Int64,
|
||||
Float32_ Float32,
|
||||
Float64_ Float64,
|
||||
String_ String,
|
||||
Date_ Date,
|
||||
DateTime_ DateTime,
|
||||
Parent UInt64
|
||||
) ENGINE = Log
|
185
dbms/tests/external_dictionaries/config.xml
Normal file
185
dbms/tests/external_dictionaries/config.xml
Normal file
@ -0,0 +1,185 @@
|
||||
<?xml version="1.0"?>
|
||||
<yandex>
|
||||
<logger>
|
||||
<level>trace</level>
|
||||
<log>./data/clickhouse-server.log</log>
|
||||
<errorlog>./data/clickhouse-server.err.log</errorlog>
|
||||
<!-- never - не ротировать логи самостоятельно. Это выставлено, так как используется logrotate.
|
||||
При необходимости, можно использовать встроенный механизм ротации. Тогда укажите максимальный размер, для примера, 100M.
|
||||
-->
|
||||
<size>never</size>
|
||||
<count>50</count>
|
||||
</logger>
|
||||
|
||||
|
||||
<http_port>8124</http_port>
|
||||
<tcp_port>9001</tcp_port>
|
||||
|
||||
<!-- Порт для передачи данных между серверами. Используется для репликации. -->
|
||||
<interserver_http_port>9010</interserver_http_port>
|
||||
|
||||
<!-- Хост, использующийся другими репликами для запросов к этому серверу.
|
||||
Если не задан - используется то же самое, что выдаёт команда uname -n.
|
||||
-->
|
||||
<!--
|
||||
<interserver_http_host>example.yandex.ru</interserver_http_host>
|
||||
-->
|
||||
|
||||
<!-- Слушать указанный хост. :: - wildcard IPv6 адрес, позволяющий принимать соединения по IPv4 и IPv6 откуда угодно. -->
|
||||
<listen_host>::</listen_host>
|
||||
|
||||
<max_connections>4096</max_connections>
|
||||
<keep_alive_timeout>3</keep_alive_timeout>
|
||||
|
||||
<!-- Максимальное количество одновременно выполняющихся запросов. -->
|
||||
<max_concurrent_queries>500</max_concurrent_queries>
|
||||
|
||||
<!-- Размер кэша разжатых блоков, используемого в движках семейства MergeTree.
|
||||
Задаётся в байтах. Кэш один общий на весь сервер. Память выделяется и используется по мере необходимости.
|
||||
-->
|
||||
<uncompressed_cache_size>8589934592</uncompressed_cache_size>
|
||||
|
||||
<!-- Примерный размер кэша засечек, используемого в движках семейства MergeTree.
|
||||
Задаётся в байтах. Кэш один общий на весь сервер. Память выделяется и используется по мере необходимости.
|
||||
-->
|
||||
<mark_cache_size>5368709120</mark_cache_size>
|
||||
|
||||
|
||||
<!-- Путь к директории с данными, включая слеш на конце. -->
|
||||
<path>./clickhouse/</path>
|
||||
|
||||
<!-- Путь к директории с временными данными, возникающими при обработке тяжёлых запросов. -->
|
||||
<tmp_path>./clickhouse/tmp/</tmp_path>
|
||||
|
||||
<!-- Путь к файлу с конфигурацией пользователей, прав доступа, профилей настроек, квот. -->
|
||||
<users_config>users.xml</users_config>
|
||||
|
||||
<!-- Профиль настроек по-умолчанию. -->
|
||||
<default_profile>default</default_profile>
|
||||
|
||||
<!-- БД по-умолчанию. -->
|
||||
<default_database>default</default_database>
|
||||
|
||||
<!-- Группы удалённых серверов, которые могут быть подключены в таблицах типа Distributed.
|
||||
https://clickhouse.yandex-team.ru/#Distributed
|
||||
-->
|
||||
<remote_servers incl="clickhouse_remote_servers" />
|
||||
|
||||
|
||||
<!-- Если у элемента конфига присутствует атрибут incl, то в качестве значения будет использована соответствующая подстановка из другого файла.
|
||||
По-умолчанию, путь к файлу с подстановками - /etc/metrika.xml. Он может быть изменён в конфиге в элементе include_from.
|
||||
Значения подстановок указываются в элементах /yandex/имя_подстановки этого файла.
|
||||
-->
|
||||
|
||||
<!-- ZooKeeper нужен для хранения мета информации о репликах, при использовании Replicated таблиц.
|
||||
Не обязательно. Если вы не используете реплицируемые таблицы - можно не указывать.
|
||||
|
||||
См. https://clickhouse.yandex-team.ru/#%D0%A0%D0%B5%D0%BF%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85
|
||||
-->
|
||||
<zookeeper incl="zookeeper-servers" optional="true" />
|
||||
|
||||
<!-- Подстановки для параметров реплицируемых таблиц.
|
||||
Не обязательно. Если вы не используете реплицируемые таблицы - можно не указывать.
|
||||
|
||||
См. https://clickhouse.yandex-team.ru/#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5%20%D1%80%D0%B5%D0%BF%D0%BB%D0%B8%D1%86%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D1%8B%D1%85%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86
|
||||
-->
|
||||
<macros incl="macros" optional="true" />
|
||||
|
||||
|
||||
<!-- Отправка данных о работе сервера в Graphite для мониторинга. -->
|
||||
<use_graphite>false</use_graphite>
|
||||
|
||||
<!-- Интервал обновления встроенных справочников, в секундах. По-умолчанию - 3600. -->
|
||||
<builtin_dictionaries_reload_interval>3600</builtin_dictionaries_reload_interval>
|
||||
|
||||
<!-- Раскомментируйте, если включено use_graphite.
|
||||
<graphite>
|
||||
<host>127.0.0.1</host>
|
||||
<port>42000</port>
|
||||
<root_path>one_min</root_path>
|
||||
<timeout>0.1</timeout>
|
||||
</graphite>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Лог запросов. Используется, только для запросов с настройкой log_queries = 1. -->
|
||||
<query_log>
|
||||
<!-- В какую таблицу писать. Если таблицы нет, она создаётся.
|
||||
При изменении структуры лога, старая таблица переименовывается и создаётся новая.
|
||||
-->
|
||||
<database>system</database>
|
||||
<table>query_log</table>
|
||||
|
||||
<!-- Интервал сброса данных в таблицу. -->
|
||||
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
|
||||
</query_log>
|
||||
|
||||
|
||||
<!-- Следующие параметры следует задавать, если используются функции, зависящие от словарей Яндекс.Метрики.
|
||||
См. https://clickhouse.yandex-team.ru/#%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8%20%D0%B4%D0%BB%D1%8F%20%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B%20%D1%81%D0%BE%20%D1%81%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8F%D0%BC%D0%B8%20%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%9C%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8
|
||||
-->
|
||||
|
||||
<!-- путь к файлу, содержащиму иерархию регионов -->
|
||||
<!-- <path_to_regions_hierarchy_file>/opt/geo/regions_hierarchy.txt</path_to_regions_hierarchy_file> -->
|
||||
|
||||
<!-- путь к директории с файлами, содержащими имена регионов -->
|
||||
<!-- <path_to_regions_names_files>/opt/geo/</path_to_regions_names_files> -->
|
||||
|
||||
<!-- Параметры БД со словарями (UserAgent, OS, etc.) -->
|
||||
<!--
|
||||
<mysql_metrica>
|
||||
<db>conv_main</db>
|
||||
<replica>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<user>metrika</user>
|
||||
<password></password>
|
||||
<priority>1</priority>
|
||||
</replica>
|
||||
</mysql_metrica>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Конфигурационные файлы внешних словарей. Смотрите:
|
||||
https://clickhouse.yandex-team.ru/#%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B5%20%D1%81%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D0%B8
|
||||
-->
|
||||
<dictionaries_config>generated/*.xml</dictionaries_config>
|
||||
|
||||
|
||||
<!-- Настройки режима совместимости с OLAPServer.
|
||||
-->
|
||||
<!--
|
||||
<olap_compatibility>
|
||||
<port>8248</port>
|
||||
<table_for_all_counters>default.visits_all</table_for_all_counters>
|
||||
<table_for_single_counter>default.visits_layer</table_for_single_counter>
|
||||
<profile>olap_compatibility</profile>
|
||||
</olap_compatibility>
|
||||
-->
|
||||
|
||||
<!-- Раскомментируйте, если хотите сделать так, чтобы ваши данные сжимались на 30-50% лучше.
|
||||
Не нужно этого делать, если вы только начинаете использовать ClickHouse.
|
||||
-->
|
||||
<!--
|
||||
<compression>
|
||||
|
||||
<!- - Набор вариантов. Варианты проверяются подряд. Побеждает последний сработавший вариант. Если ни один не сработал, то используется lz4. - ->
|
||||
<case>
|
||||
|
||||
<!- - Условия. Должны сработать одновременно все. Часть условий могут быть не указаны. - ->
|
||||
<min_part_size>10000000000</min_part_size> <!- - Минимальный размер куска в байтах. - ->
|
||||
<min_part_size_ratio>0.01</min_part_size_ratio> <!- - Минимальный размер куска относительно всех данных таблицы. - ->
|
||||
|
||||
<!- - Какой метод сжатия выбрать. - ->
|
||||
<method>zstd</method>
|
||||
</case>
|
||||
</compression>
|
||||
-->
|
||||
|
||||
<!-- Здесь могут быть тонкие настройки работы таблиц типа MergeTree. Смотрите документацию в исходниках, в файле MergeTreeSettings.h -->
|
||||
<!--
|
||||
<merge_tree>
|
||||
<max_suspicious_broken_parts>5</max_suspicious_broken_parts>
|
||||
</merge_tree>
|
||||
-->
|
||||
</yandex>
|
371
dbms/tests/external_dictionaries/generate_and_test.py
Normal file
371
dbms/tests/external_dictionaries/generate_and_test.py
Normal file
@ -0,0 +1,371 @@
|
||||
import os
|
||||
import json
|
||||
import subprocess
|
||||
import time
|
||||
from itertools import chain
|
||||
from os import system
|
||||
|
||||
wait_for_loading_sleep_time_sec = 3
|
||||
continue_on_error = False
|
||||
|
||||
clickhouse_binary = 'clickhouse-client'
|
||||
prefix = base_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
generated_prefix = prefix + '/generated/'
|
||||
|
||||
# [ name, key_type, has_parent ]
|
||||
dictionaries = [
|
||||
# Simple key dictionaries
|
||||
[ 'file_flat', 0, True ],
|
||||
[ 'clickhouse_flat', 0, True ],
|
||||
[ 'mysql_flat', 0, True ],
|
||||
[ 'mongodb_flat', 0, True ],
|
||||
|
||||
[ 'file_hashed', 0, True ],
|
||||
[ 'clickhouse_hashed', 0, True ],
|
||||
[ 'mysql_hashed', 0, True ],
|
||||
[ 'mongodb_hashed', 0, True ],
|
||||
|
||||
[ 'clickhouse_cache', 0, True ],
|
||||
[ 'mysql_cache', 0, True ],
|
||||
[ 'mongodb_cache', 0, True ],
|
||||
|
||||
# Complex key dictionaries with (UInt8, UInt8) key
|
||||
[ 'file_complex_integers_key_hashed', 1, False ],
|
||||
[ 'clickhouse_complex_integers_key_hashed', 1, False ],
|
||||
[ 'mysql_complex_integers_key_hashed', 1, False ],
|
||||
[ 'mongodb_complex_integers_key_hashed', 1, False ],
|
||||
|
||||
[ 'clickhouse_complex_integers_key_cache', 1, False ],
|
||||
[ 'mysql_complex_integers_key_cache', 1, False ],
|
||||
[ 'mongodb_complex_integers_key_cache', 1, False ],
|
||||
|
||||
# Complex key dictionaries with (String, UInt8) key
|
||||
[ 'file_complex_mixed_key_hashed', 2, False ],
|
||||
[ 'clickhouse_complex_mixed_key_hashed', 2, False ],
|
||||
[ 'mysql_complex_mixed_key_hashed', 2, False ],
|
||||
[ 'mongodb_complex_mixed_key_hashed', 2, False ],
|
||||
|
||||
[ 'clickhouse_complex_mixed_key_cache', 2, False ],
|
||||
[ 'mysql_complex_mixed_key_cache', 2, False ],
|
||||
[ 'mongodb_complex_mixed_key_cache', 2, False ],
|
||||
]
|
||||
|
||||
files = [ 'key_simple.tsv', 'key_complex_integers.tsv', 'key_complex_mixed.tsv' ]
|
||||
|
||||
types = [
|
||||
'UInt8', 'UInt16', 'UInt32', 'UInt64',
|
||||
'Int8', 'Int16', 'Int32', 'Int64',
|
||||
'Float32', 'Float64',
|
||||
'String',
|
||||
'Date', 'DateTime'
|
||||
]
|
||||
|
||||
explicit_defaults = [
|
||||
'42', '42', '42', '42',
|
||||
'-42', '-42', '-42', '-42',
|
||||
'1.5', '1.6',
|
||||
"'explicit-default'",
|
||||
"'2015-01-01'", "'2015-01-01 00:00:00'"
|
||||
]
|
||||
|
||||
implicit_defaults = [
|
||||
'1', '1', '1', '1',
|
||||
'-1', '-1', '-1', '-1',
|
||||
'2.71828', '2.71828',
|
||||
'implicit-default',
|
||||
'2015-11-25', '2015-11-25 00:00:00'
|
||||
]
|
||||
|
||||
def call(args, out_filename):
|
||||
with open(out_filename, 'w') as file:
|
||||
subprocess.check_call(args, stdout=file)
|
||||
|
||||
def generate_data():
|
||||
def comma_separated(iterable):
|
||||
return ', '.join(iterable)
|
||||
|
||||
def columns():
|
||||
return map(lambda t: t + '_', types)
|
||||
|
||||
key_columns = [
|
||||
[ 'id' ],
|
||||
[ 'key0', 'key1' ],
|
||||
[ 'key0_str', 'key1' ]
|
||||
]
|
||||
|
||||
print 'Creating ClickHouse table'
|
||||
# create ClickHouse table via insert select
|
||||
system('cat source.tsv | {ch} --port 9001 -m -n --query "'
|
||||
'create database if not exists test;'
|
||||
'drop table if exists test.dictionary_source;'
|
||||
'create table test.dictionary_source ('
|
||||
'id UInt64, key0 UInt8, key0_str String, key1 UInt8,'
|
||||
'UInt8_ UInt8, UInt16_ UInt16, UInt32_ UInt32, UInt64_ UInt64,'
|
||||
'Int8_ Int8, Int16_ Int16, Int32_ Int32, Int64_ Int64,'
|
||||
'Float32_ Float32, Float64_ Float64,'
|
||||
'String_ String,'
|
||||
'Date_ Date, DateTime_ DateTime, Parent UInt64'
|
||||
') engine=Log; insert into test.dictionary_source format TabSeparated'
|
||||
'"'.format(ch=clickhouse_binary))
|
||||
|
||||
# generate 3 files with different key types
|
||||
print 'Creating .tsv files'
|
||||
file_source_query = 'select %s from test.dictionary_source format TabSeparated;'
|
||||
for file, keys in zip(files, key_columns):
|
||||
query = file_source_query % comma_separated(chain(keys, columns(), [ 'Parent' ] if 1 == len(keys) else []))
|
||||
call([ clickhouse_binary, '--port', '9001', '--query', query ], 'generated/' + file)
|
||||
|
||||
# create MySQL table from complete_query
|
||||
print 'Creating MySQL table'
|
||||
subprocess.check_call('echo "'
|
||||
'create database if not exists test;'
|
||||
'drop table if exists test.dictionary_source;'
|
||||
'create table test.dictionary_source ('
|
||||
'id tinyint unsigned, key0 tinyint unsigned, key0_str text, key1 tinyint unsigned, '
|
||||
'UInt8_ tinyint unsigned, UInt16_ smallint unsigned, UInt32_ int unsigned, UInt64_ bigint unsigned, '
|
||||
'Int8_ tinyint, Int16_ smallint, Int32_ int, Int64_ bigint, '
|
||||
'Float32_ float, Float64_ double, '
|
||||
'String_ text, Date_ date, DateTime_ datetime, Parent bigint unsigned'
|
||||
');'
|
||||
'load data local infile \'{0}/source.tsv\' into table test.dictionary_source;" | mysql --local-infile=1'
|
||||
.format(prefix), shell=True)
|
||||
|
||||
# create MongoDB collection from complete_query via JSON file
|
||||
print 'Creating MongoDB collection'
|
||||
table_rows = json.loads(subprocess.check_output([
|
||||
clickhouse_binary, '--port', '9001',
|
||||
'--query',
|
||||
"select * from test.dictionary_source where not ignore(" \
|
||||
"concat('new Date(\\'', toString(Date_), '\\')') as Date_, " \
|
||||
"concat('new Date(\\'', toString(DateTime_), '\\')') as DateTime_" \
|
||||
") format JSON"
|
||||
]))['data']
|
||||
|
||||
# ClickHouse outputs 64-bit wide integers in double-quotes, convert them
|
||||
for row in table_rows:
|
||||
for column in [u'id', u'UInt64_', u'Int64_', u'Parent']:
|
||||
row[column] = int(row[column])
|
||||
|
||||
source_for_mongo = json.dumps(table_rows).replace(')"', ')').replace('"new', 'new')
|
||||
open('generated/full.json', 'w').write('db.dictionary_source.drop(); db.dictionary_source.insert(%s);' % source_for_mongo)
|
||||
result = system('cat generated/full.json | mongo --quiet > /dev/null')
|
||||
if result != 0:
|
||||
print 'Could not create MongoDB collection'
|
||||
exit(-1)
|
||||
|
||||
def generate_dictionaries():
|
||||
dictionary_skeleton = '''
|
||||
<dictionaries>
|
||||
<dictionary>
|
||||
<name>{name}</name>
|
||||
|
||||
<source>
|
||||
{source}
|
||||
</source>
|
||||
|
||||
<lifetime>
|
||||
<min>0</min>
|
||||
<max>0</max>
|
||||
</lifetime>
|
||||
|
||||
<layout>
|
||||
{layout}
|
||||
</layout>
|
||||
|
||||
<structure>
|
||||
{key}
|
||||
|
||||
%s
|
||||
|
||||
{parent}
|
||||
</structure>
|
||||
</dictionary>
|
||||
</dictionaries>'''
|
||||
attribute_skeleton = '''
|
||||
<attribute>
|
||||
<name>%s_</name>
|
||||
<type>%s</type>
|
||||
<null_value>%s</null_value>
|
||||
</attribute>
|
||||
'''
|
||||
|
||||
dictionary_skeleton =\
|
||||
dictionary_skeleton % reduce(lambda xml, (type, default): xml + attribute_skeleton % (type, type, default),
|
||||
zip(types, implicit_defaults), '')
|
||||
|
||||
source_file = '''
|
||||
<file>
|
||||
<path>%s</path>
|
||||
<format>TabSeparated</format>
|
||||
</file>
|
||||
'''
|
||||
source_clickhouse = '''
|
||||
<clickhouse>
|
||||
<host>127.0.0.1</host>
|
||||
<port>9001</port>
|
||||
<user>default</user>
|
||||
<password></password>
|
||||
<db>test</db>
|
||||
<table>dictionary_source</table>
|
||||
</clickhouse>
|
||||
'''
|
||||
source_mysql = '''
|
||||
<mysql>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<user>root</user>
|
||||
<password></password>
|
||||
<db>test</db>
|
||||
<table>dictionary_source</table>
|
||||
</mysql>
|
||||
'''
|
||||
source_mongodb = '''
|
||||
<mongodb>
|
||||
<host>localhost</host>
|
||||
<port>27017</port>
|
||||
<user></user>
|
||||
<password></password>
|
||||
<db>test</db>
|
||||
<collection>dictionary_source</collection>
|
||||
</mongodb>
|
||||
'''
|
||||
|
||||
layout_flat = '<flat />'
|
||||
layout_hashed = '<hashed />'
|
||||
layout_cache = '<cache><size_in_cells>128</size_in_cells></cache>'
|
||||
layout_complex_key_hashed = '<complex_key_hashed />'
|
||||
layout_complex_key_cache = '<complex_key_cache><size_in_cells>128</size_in_cells></complex_key_cache>'
|
||||
|
||||
key_simple = '''
|
||||
<id>
|
||||
<name>id</name>
|
||||
</id>
|
||||
'''
|
||||
key_complex_integers = '''
|
||||
<key>
|
||||
<attribute>
|
||||
<name>key0</name>
|
||||
<type>UInt8</type>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>key1</name>
|
||||
<type>UInt8</type>
|
||||
</attribute>
|
||||
</key>
|
||||
'''
|
||||
key_complex_mixed = '''
|
||||
<key>
|
||||
<attribute>
|
||||
<name>key0_str</name>
|
||||
<type>String</type>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>key1</name>
|
||||
<type>UInt8</type>
|
||||
</attribute>
|
||||
</key>
|
||||
'''
|
||||
|
||||
keys = [ key_simple, key_complex_integers, key_complex_mixed ]
|
||||
|
||||
parent_attribute = '''
|
||||
<attribute>
|
||||
<name>Parent</name>
|
||||
<type>UInt64</type>
|
||||
<hierarchical>true</hierarchical>
|
||||
<null_value>0</null_value>
|
||||
</attribute>
|
||||
'''
|
||||
|
||||
sources_and_layouts = [
|
||||
# Simple key dictionaries
|
||||
[ source_file % (generated_prefix + files[0]), layout_flat],
|
||||
[ source_clickhouse, layout_flat ],
|
||||
[ source_mysql, layout_flat ],
|
||||
[ source_mongodb, layout_flat ],
|
||||
|
||||
[ source_file % (generated_prefix + files[0]), layout_hashed],
|
||||
[ source_clickhouse, layout_hashed ],
|
||||
[ source_mysql, layout_hashed ],
|
||||
[ source_mongodb, layout_hashed ],
|
||||
|
||||
[ source_clickhouse, layout_cache ],
|
||||
[ source_mysql, layout_cache ],
|
||||
[ source_mongodb, layout_cache ],
|
||||
|
||||
# Complex key dictionaries with (UInt8, UInt8) key
|
||||
[ source_file % (generated_prefix + files[1]), layout_complex_key_hashed],
|
||||
[ source_clickhouse, layout_complex_key_hashed ],
|
||||
[ source_mysql, layout_complex_key_hashed ],
|
||||
[ source_mongodb, layout_complex_key_hashed ],
|
||||
|
||||
[ source_clickhouse, layout_complex_key_cache ],
|
||||
[ source_mysql, layout_complex_key_cache ],
|
||||
[ source_mongodb, layout_complex_key_cache ],
|
||||
|
||||
# Complex key dictionaries with (String, UInt8) key
|
||||
[ source_file % (generated_prefix + files[2]), layout_complex_key_hashed],
|
||||
[ source_clickhouse, layout_complex_key_hashed ],
|
||||
[ source_mysql, layout_complex_key_hashed ],
|
||||
[ source_mongodb, layout_complex_key_hashed ],
|
||||
|
||||
[ source_clickhouse, layout_complex_key_cache ],
|
||||
[ source_mysql, layout_complex_key_cache ],
|
||||
[ source_mongodb, layout_complex_key_cache ],
|
||||
]
|
||||
|
||||
for (name, key_idx, has_parent), (source, layout) in zip(dictionaries, sources_and_layouts):
|
||||
filename = 'generated/dictionary_%s.xml' % name
|
||||
with open(filename, 'w') as file:
|
||||
dictionary_xml = dictionary_skeleton.format(
|
||||
key = keys[key_idx], parent = parent_attribute if has_parent else '', **locals())
|
||||
file.write(dictionary_xml)
|
||||
|
||||
def run_tests():
|
||||
keys = [ 'toUInt64(n)', '(n, n)', '(toString(n), n)' ]
|
||||
dict_get_query_skeleton = "select dictGet{type}('{name}', '{type}_', {key}) array join range(8) as n;"
|
||||
dict_has_query_skeleton = "select dictHas('{name}', {key}) array join range(8) as n;"
|
||||
dict_get_or_default_query_skeleton = "select dictGet{type}OrDefault('{name}', '{type}_', {key}, to{type}({default})) array join range(8) as n;"
|
||||
dict_hierarchy_query_skeleton = "select dictGetHierarchy('{name}' as d, key), dictIsIn(d, key, toUInt64(1)), dictIsIn(d, key, key) array join range(toUInt64(8)) as key;"
|
||||
|
||||
def test_query(dict, query, reference, name):
|
||||
result = system('{ch} --port 9001 --query "{query}" | diff - reference/{reference}.reference'.format(ch=clickhouse_binary, **locals()))
|
||||
|
||||
if result != 0:
|
||||
print 'Dictionary ' + dict + ' has failed test ' + name + '\n'
|
||||
if not continue_on_error:
|
||||
exit(-1)
|
||||
|
||||
print 'Waiting for dictionaries to load...'
|
||||
time.sleep(wait_for_loading_sleep_time_sec)
|
||||
|
||||
# the actual tests
|
||||
for (name, key_idx, has_parent) in dictionaries:
|
||||
key = keys[key_idx]
|
||||
print 'Testing dictionary', name
|
||||
|
||||
# query dictHas
|
||||
test_query(name, dict_has_query_skeleton.format(**locals()), 'has', 'dictHas')
|
||||
|
||||
# query dictGet*
|
||||
for type, default in zip(types, explicit_defaults):
|
||||
test_query(name,
|
||||
dict_get_query_skeleton.format(**locals()),
|
||||
type, 'dictGet' + type)
|
||||
test_query(name,
|
||||
dict_get_or_default_query_skeleton.format(**locals()),
|
||||
type + 'OrDefault', 'dictGet' + type + 'OrDefault')
|
||||
|
||||
# query dictGetHierarchy, dictIsIn
|
||||
if has_parent:
|
||||
test_query(name,
|
||||
dict_hierarchy_query_skeleton.format(**locals()),
|
||||
'hierarchy', ' for dictGetHierarchy, dictIsIn')
|
||||
|
||||
generate_data()
|
||||
generate_dictionaries()
|
||||
run_tests()
|
||||
|
||||
print 'Done'
|
2
dbms/tests/external_dictionaries/generated/.gitignore
vendored
Normal file
2
dbms/tests/external_dictionaries/generated/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
@ -0,0 +1,8 @@
|
||||
2007-12-27
|
||||
2037-06-02
|
||||
1978-08-08
|
||||
1973-06-28
|
||||
2015-11-25
|
||||
2015-11-25
|
||||
2015-11-25
|
||||
2015-11-25
|
@ -0,0 +1,8 @@
|
||||
2007-12-27
|
||||
2037-06-02
|
||||
1978-08-08
|
||||
1973-06-28
|
||||
2015-01-01
|
||||
2015-01-01
|
||||
2015-01-01
|
||||
2015-01-01
|
@ -0,0 +1,8 @@
|
||||
1970-01-01 06:51:14
|
||||
1970-01-01 09:50:24
|
||||
1970-01-01 03:52:21
|
||||
1970-01-01 03:21:14
|
||||
2015-11-25 00:00:00
|
||||
2015-11-25 00:00:00
|
||||
2015-11-25 00:00:00
|
||||
2015-11-25 00:00:00
|
@ -0,0 +1,8 @@
|
||||
1970-01-01 06:51:14
|
||||
1970-01-01 09:50:24
|
||||
1970-01-01 03:52:21
|
||||
1970-01-01 03:21:14
|
||||
2015-01-01 00:00:00
|
||||
2015-01-01 00:00:00
|
||||
2015-01-01 00:00:00
|
||||
2015-01-01 00:00:00
|
@ -0,0 +1,8 @@
|
||||
0
|
||||
1.5
|
||||
3
|
||||
4.5
|
||||
2.71828
|
||||
2.71828
|
||||
2.71828
|
||||
2.71828
|
@ -0,0 +1,8 @@
|
||||
0
|
||||
1.5
|
||||
3
|
||||
4.5
|
||||
1.5
|
||||
1.5
|
||||
1.5
|
||||
1.5
|
@ -0,0 +1,8 @@
|
||||
0
|
||||
1.5
|
||||
3
|
||||
4.5
|
||||
2.71828
|
||||
2.71828
|
||||
2.71828
|
||||
2.71828
|
@ -0,0 +1,8 @@
|
||||
0
|
||||
1.5
|
||||
3
|
||||
4.5
|
||||
1.6
|
||||
1.6
|
||||
1.6
|
||||
1.6
|
@ -0,0 +1,8 @@
|
||||
13874
|
||||
-8144
|
||||
-29627
|
||||
1274
|
||||
-1
|
||||
-1
|
||||
-1
|
||||
-1
|
@ -0,0 +1,8 @@
|
||||
13874
|
||||
-8144
|
||||
-29627
|
||||
1274
|
||||
-42
|
||||
-42
|
||||
-42
|
||||
-42
|
@ -0,0 +1,8 @@
|
||||
980694578
|
||||
-211165136
|
||||
1447922757
|
||||
1029309690
|
||||
-1
|
||||
-1
|
||||
-1
|
||||
-1
|
@ -0,0 +1,8 @@
|
||||
980694578
|
||||
-211165136
|
||||
1447922757
|
||||
1029309690
|
||||
-42
|
||||
-42
|
||||
-42
|
||||
-42
|
@ -0,0 +1,8 @@
|
||||
980694579
|
||||
-211165135
|
||||
1447922758
|
||||
1029309691
|
||||
-1
|
||||
-1
|
||||
-1
|
||||
-1
|
@ -0,0 +1,8 @@
|
||||
980694579
|
||||
-211165135
|
||||
1447922758
|
||||
1029309691
|
||||
-42
|
||||
-42
|
||||
-42
|
||||
-42
|
@ -0,0 +1,8 @@
|
||||
50
|
||||
48
|
||||
69
|
||||
-6
|
||||
-1
|
||||
-1
|
||||
-1
|
||||
-1
|
@ -0,0 +1,8 @@
|
||||
50
|
||||
48
|
||||
69
|
||||
-6
|
||||
-42
|
||||
-42
|
||||
-42
|
||||
-42
|
@ -0,0 +1,8 @@
|
||||
4761183170873013810
|
||||
10577349846663553072
|
||||
18198135717204167749
|
||||
9624464864560415994
|
||||
implicit-default
|
||||
implicit-default
|
||||
implicit-default
|
||||
implicit-default
|
@ -0,0 +1,8 @@
|
||||
4761183170873013810
|
||||
10577349846663553072
|
||||
18198135717204167749
|
||||
9624464864560415994
|
||||
explicit-default
|
||||
explicit-default
|
||||
explicit-default
|
||||
explicit-default
|
@ -0,0 +1,8 @@
|
||||
13874
|
||||
57392
|
||||
35909
|
||||
1274
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
13874
|
||||
57392
|
||||
35909
|
||||
1274
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
@ -0,0 +1,8 @@
|
||||
980694578
|
||||
4083802160
|
||||
1447922757
|
||||
1029309690
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
980694578
|
||||
4083802160
|
||||
1447922757
|
||||
1029309690
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
@ -0,0 +1,8 @@
|
||||
980694579
|
||||
4083802161
|
||||
1447922758
|
||||
1029309691
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
980694579
|
||||
4083802161
|
||||
1447922758
|
||||
1029309691
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
@ -0,0 +1,8 @@
|
||||
50
|
||||
48
|
||||
69
|
||||
250
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
50
|
||||
48
|
||||
69
|
||||
250
|
||||
42
|
||||
42
|
||||
42
|
||||
42
|
8
dbms/tests/external_dictionaries/reference/has.reference
Normal file
8
dbms/tests/external_dictionaries/reference/has.reference
Normal file
@ -0,0 +1,8 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
@ -0,0 +1,8 @@
|
||||
[] 0 0
|
||||
[1] 1 1
|
||||
[2,1] 1 1
|
||||
[3,2,1] 1 1
|
||||
[4] 0 1
|
||||
[5] 0 1
|
||||
[6] 0 1
|
||||
[7] 0 1
|
86
dbms/tests/external_dictionaries/run.sh
Executable file
86
dbms/tests/external_dictionaries/run.sh
Executable file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
|
||||
# MySQL
|
||||
if [ -z $(which mysqld) ] || [ -z $(which mysqld) ]; then
|
||||
echo 'Installing MySQL'
|
||||
sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password password '
|
||||
sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password '
|
||||
sudo apt-get -y --force-yes install mysql-server >/dev/null
|
||||
which mysqld >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'Failed installing mysql-server'
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo 'Installed mysql-server'
|
||||
else
|
||||
echo 'MySQL already installed'
|
||||
fi
|
||||
|
||||
MY_CNF=/etc/mysql/my.cnf
|
||||
LOCAL_INFILE_ENABLED=$(grep 'local-infile' $MY_CNF | cut -d= -f2)
|
||||
if [ -z $LOCAL_INFILE_ENABLED ] || [ $LOCAL_INFILE_ENABLED != 1 ]; then
|
||||
echo 'Enabling local-infile support'
|
||||
if [ -z "$(grep 'local-infile' $MY_CNF)" ]; then
|
||||
# add local-infile
|
||||
MY_CNF_PATTERN='/\[mysqld\]/alocal-infile = 1'
|
||||
else
|
||||
# edit local-infile just in case
|
||||
MY_CNF_PATTERN='s/local-infile.*/local-infile = 1/'
|
||||
fi
|
||||
sudo sed -i "$MY_CNF_PATTERN" $MY_CNF
|
||||
|
||||
echo 'Enabled local-infile support for mysql'
|
||||
sudo /etc/init.d/mysql stop
|
||||
sudo /etc/init.d/mysql start
|
||||
else
|
||||
echo 'Support for local-infile already present'
|
||||
echo 'select 1;' | mysql &>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
sudo /etc/init.d/mysql start
|
||||
else
|
||||
echo 'MySQL already started'
|
||||
fi
|
||||
fi
|
||||
|
||||
# MongoDB
|
||||
if [ -z $(which mongod) ] || [ -z $(which mongo) ]; then
|
||||
echo 'Installing MongoDB'
|
||||
MONGODB_ORG_VERSION=3.0.6
|
||||
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 &>/dev/null
|
||||
echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list >/dev/null
|
||||
sudo apt-get update &>/dev/null
|
||||
sudo apt-get install -y mongodb-org=$MONGODB_ORG_VERSION >/dev/null
|
||||
which mongod >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'Failed installing mongodb-org'
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo "Installed mongodb-org $MONGODB_ORG_VERSION"
|
||||
fi
|
||||
|
||||
echo | mongo &>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
sudo service mongod start
|
||||
else
|
||||
echo 'MongoDB already started'
|
||||
fi
|
||||
|
||||
# ClickHouse
|
||||
clickhouse-server &>/dev/null &
|
||||
sleep 3
|
||||
result=$(clickhouse-client --port 9001 --query 'select 1')
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'Failed to start ClickHouse'
|
||||
exit -1
|
||||
fi
|
||||
echo 'Started ClickHouse server'
|
||||
PID=$(grep PID clickhouse/status | sed 's/PID: //')
|
||||
python ./generate_and_test.py
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'Some test failed'
|
||||
fi
|
||||
kill -SIGTERM $PID
|
||||
#wait $PID
|
||||
echo 'Stopped ClickHouse server'
|
4
dbms/tests/external_dictionaries/source.tsv
Normal file
4
dbms/tests/external_dictionaries/source.tsv
Normal file
@ -0,0 +1,4 @@
|
||||
0 0 0 0 50 13874 980694578 980694579 50 13874 980694578 980694579 0 0 4761183170873013810 2007-12-27 1970-01-01 06:51:14 0
|
||||
1 1 1 1 48 57392 4083802160 4083802161 48 -8144 -211165136 -211165135 1.5 1.5 10577349846663553072 2037-06-02 1970-01-01 09:50:24 0
|
||||
2 2 2 2 69 35909 1447922757 1447922758 69 -29627 1447922757 1447922758 3 3 18198135717204167749 1978-08-08 1970-01-01 03:52:21 1
|
||||
3 3 3 3 250 1274 1029309690 1029309691 -6 1274 1029309690 1029309691 4.5 4.5 9624464864560415994 1973-06-28 1970-01-01 03:21:14 2
|
|
100
dbms/tests/external_dictionaries/users.xml
Normal file
100
dbms/tests/external_dictionaries/users.xml
Normal file
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0"?>
|
||||
<yandex>
|
||||
<!-- Профили настроек. -->
|
||||
<profiles>
|
||||
<!-- Настройки по-умолчанию -->
|
||||
<default>
|
||||
<!-- Максимальное потребление оперативки одним запросом (байт). -->
|
||||
<max_memory_usage>10000000000</max_memory_usage>
|
||||
|
||||
<!-- Использовать ли кэш разжатых блоков. Имеет смысл только для большого количества мелких запросов. -->
|
||||
<use_uncompressed_cache>0</use_uncompressed_cache>
|
||||
|
||||
<!-- Как выбирать реплику ClickHouse.
|
||||
random - среди реплик с минимальным количеством ошибок выбирается случайная
|
||||
nearest_hostname - среди реплик с минимальным количеством ошибок выбирается реплика
|
||||
с минимальным количеством отличающихся символов между именем реплики и именем локального хоста.
|
||||
in_order - реплики перебираются в точности в таком порядке, в каком они указаны.
|
||||
-->
|
||||
<load_balancing>random</load_balancing>
|
||||
</default>
|
||||
|
||||
<!-- Разрешает запросы только на чтение. -->
|
||||
<readonly>
|
||||
<readonly>1</readonly>
|
||||
</readonly>
|
||||
</profiles>
|
||||
|
||||
<!-- Пользователи и ACL. -->
|
||||
<users>
|
||||
<!-- Если имя пользователя не указано, используется пользователь default. -->
|
||||
<default>
|
||||
<!-- Пароль можно указать либо в открытом виде, либо в виде SHA256 (в hex формате).
|
||||
|
||||
Если вы хотите указать пароль в открытом виде (не рекомендуется), то укажите его в элементе password.
|
||||
Пример: <password>qwerty</password>.
|
||||
Пароль может быть пустым.
|
||||
|
||||
Если вы хотите указать SHA256, то укажите его в элементе password_sha256_hex.
|
||||
Пример: <password_sha256_hex>65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5</password_sha256_hex>
|
||||
|
||||
Как сгенерировать хороший пароль:
|
||||
Выполните: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-'
|
||||
На первой строке будет пароль, а на второй - его SHA256.
|
||||
-->
|
||||
<password></password>
|
||||
|
||||
<!-- Список сетей, из которых разрешён доступ.
|
||||
|
||||
Для доступа отовсюду, пропишите <ip>::/0</ip>
|
||||
|
||||
Каждый элемент списка имеет одну из следующих форм:
|
||||
<ip> IP-адрес или маска подсети. Например, 213.180.204.3 или 10.0.0.1/8 или 2a02:6b8::3 или 2a02:6b8::3/64.
|
||||
<host> Имя хоста. Например: mtcalc01. Для проверки делается DNS-запрос, и все полученные адреса сравниваются с адресом клиента.
|
||||
<host_regexp> Регексп для имён хостов. Например, ^mtlog\d\d-\d\d-\d\.yandex\.ru$
|
||||
Для проверки, для адреса клиента делается DNS PTR-запрос и к результату применяется регексп.
|
||||
Потом для результата PTR-запроса делается снова DNS-запрос, и все полученные адреса сравниваются с адресом клиента.
|
||||
Настоятельно рекомендуется, чтобы регексп заканчивался на \.yandex\.ru$.
|
||||
-->
|
||||
<networks incl="networks" replace="replace">
|
||||
<ip>::1</ip>
|
||||
<ip>127.0.0.1</ip>
|
||||
</networks>
|
||||
|
||||
<!-- Профиль настроек, использующийся для пользователя. -->
|
||||
<profile>default</profile>
|
||||
|
||||
<!-- Квота, использующаяся для пользователя. -->
|
||||
<quota>default</quota>
|
||||
</default>
|
||||
|
||||
<readonly>
|
||||
<password></password>
|
||||
<networks incl="networks" replace="replace">
|
||||
<ip>::1</ip>
|
||||
<ip>127.0.0.1</ip>
|
||||
</networks>
|
||||
<profile>readonly</profile>
|
||||
<quota>default</quota>
|
||||
</readonly>
|
||||
</users>
|
||||
|
||||
<!-- Квоты. -->
|
||||
<quotas>
|
||||
<!-- Имя квоты. -->
|
||||
<default>
|
||||
<!-- Ограничения за интервал времени. Можно задать много интервалов с разными ограничениями. -->
|
||||
<interval>
|
||||
<!-- Длина интервала. -->
|
||||
<duration>3600</duration>
|
||||
|
||||
<!-- Без ограничений. Просто считать соответствующие данные за указанный интервал. -->
|
||||
<queries>0</queries>
|
||||
<errors>0</errors>
|
||||
<result_rows>0</result_rows>
|
||||
<read_rows>0</read_rows>
|
||||
<execution_time>0</execution_time>
|
||||
</interval>
|
||||
</default>
|
||||
</quotas>
|
||||
</yandex>
|
Loading…
Reference in New Issue
Block a user