mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge branch 'master' into database_replicated
This commit is contained in:
commit
1aac7b3471
@ -56,7 +56,7 @@ $ echo 'SELECT version()' | curl 'http://localhost:8123/' --data-binary @-
|
||||
20.12.3.3
|
||||
```
|
||||
|
||||
### Volumes
|
||||
### Volumes
|
||||
|
||||
Typically you may want to mount the following folders inside your container to archieve persistency:
|
||||
|
||||
@ -76,7 +76,7 @@ You may also want to mount:
|
||||
* `/etc/clickhouse-server/usert.d/*.xml` - files with use settings adjustmenets
|
||||
* `/docker-entrypoint-initdb.d/` - folder with database initialization scripts (see below).
|
||||
|
||||
### Linux capabilities
|
||||
### Linux capabilities
|
||||
|
||||
ClickHouse has some advanced functionality which requite enabling several [linux capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html).
|
||||
|
||||
@ -113,10 +113,10 @@ $ docker run --rm -e CLICKHOUSE_UID=0 -e CLICKHOUSE_GID=0 --name clickhouse-serv
|
||||
|
||||
### How to create default database and user on starting
|
||||
|
||||
Sometimes you may want to create user (user named `default` is used by default) and database on image starting. You can do it using environment variables `CLICKHOUSE_DB`, `CLICKHOUSE_USER` and `CLICKHOUSE_PASSWORD`:
|
||||
Sometimes you may want to create user (user named `default` is used by default) and database on image starting. You can do it using environment variables `CLICKHOUSE_DB`, `CLICKHOUSE_USER`, `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT` and `CLICKHOUSE_PASSWORD`:
|
||||
|
||||
```
|
||||
$ docker run --rm -e CLICKHOUSE_DB=my_database -e CLICKHOUSE_USER=username -e CLICKHOUSE_PASSWORD=password -p 9000:9000/tcp yandex/clickhouse-server
|
||||
$ docker run --rm -e CLICKHOUSE_DB=my_database -e CLICKHOUSE_USER=username -e CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1 -e CLICKHOUSE_PASSWORD=password -p 9000:9000/tcp yandex/clickhouse-server
|
||||
```
|
||||
|
||||
## How to extend this image
|
||||
|
@ -54,6 +54,7 @@ FORMAT_SCHEMA_PATH="$(clickhouse extract-from-config --config-file "$CLICKHOUSE_
|
||||
CLICKHOUSE_USER="${CLICKHOUSE_USER:-default}"
|
||||
CLICKHOUSE_PASSWORD="${CLICKHOUSE_PASSWORD:-}"
|
||||
CLICKHOUSE_DB="${CLICKHOUSE_DB:-}"
|
||||
CLICKHOUSE_ACCESS_MANAGEMENT="${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-0}"
|
||||
|
||||
for dir in "$DATA_DIR" \
|
||||
"$ERROR_LOG_DIR" \
|
||||
@ -97,6 +98,7 @@ if [ -n "$CLICKHOUSE_USER" ] && [ "$CLICKHOUSE_USER" != "default" ] || [ -n "$CL
|
||||
</networks>
|
||||
<password>${CLICKHOUSE_PASSWORD}</password>
|
||||
<quota>default</quota>
|
||||
<access_management>${CLICKHOUSE_ACCESS_MANAGEMENT}</access_management>
|
||||
</${CLICKHOUSE_USER}>
|
||||
</users>
|
||||
</yandex>
|
||||
|
@ -312,7 +312,7 @@ Enables or disables parsing enum values as enum ids for TSV input format.
|
||||
Possible values:
|
||||
|
||||
- 0 — Enum values are parsed as values.
|
||||
- 1 — Enum values are parsed as enum IDs
|
||||
- 1 — Enum values are parsed as enum IDs.
|
||||
|
||||
Default value: 0.
|
||||
|
||||
|
@ -133,10 +133,9 @@ For example:
|
||||
|
||||
### cutToFirstSignificantSubdomainCustom {#cuttofirstsignificantsubdomaincustom}
|
||||
|
||||
Same as `cutToFirstSignificantSubdomain` but accept custom TLD list name, useful if:
|
||||
Returns the part of the domain that includes top-level subdomains up to the first significant subdomain. Accepts custom [TLD list](https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains) name.
|
||||
|
||||
- you need fresh TLD list,
|
||||
- or you have custom.
|
||||
Can be useful if you need fresh TLD list or you have custom.
|
||||
|
||||
Configuration example:
|
||||
|
||||
@ -149,21 +148,150 @@ Configuration example:
|
||||
</top_level_domains_lists>
|
||||
```
|
||||
|
||||
Example:
|
||||
**Syntax**
|
||||
|
||||
- `cutToFirstSignificantSubdomain('https://news.yandex.com.tr/', 'public_suffix_list') = 'yandex.com.tr'`.
|
||||
``` sql
|
||||
cutToFirstSignificantSubdomain(URL, TLD)
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `URL` — URL. [String](../../sql-reference/data-types/string.md).
|
||||
- `TLD` — Custom TLD list name. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Part of the domain that includes top-level subdomains up to the first significant subdomain.
|
||||
|
||||
Type: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```text
|
||||
┌─cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐
|
||||
│ foo.there-is-no-such-domain │
|
||||
└───────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**See Also**
|
||||
|
||||
- [firstSignificantSubdomain](#firstsignificantsubdomain).
|
||||
|
||||
### cutToFirstSignificantSubdomainCustomWithWWW {#cuttofirstsignificantsubdomaincustomwithwww}
|
||||
|
||||
Same as `cutToFirstSignificantSubdomainWithWWW` but accept custom TLD list name.
|
||||
Returns the part of the domain that includes top-level subdomains up to the first significant subdomain without stripping `www`. Accepts custom TLD list name.
|
||||
|
||||
Can be useful if you need fresh TLD list or you have custom.
|
||||
|
||||
Configuration example:
|
||||
|
||||
```xml
|
||||
<!-- <top_level_domains_path>/var/lib/clickhouse/top_level_domains/</top_level_domains_path> -->
|
||||
<top_level_domains_lists>
|
||||
<!-- https://publicsuffix.org/list/public_suffix_list.dat -->
|
||||
<public_suffix_list>public_suffix_list.dat</public_suffix_list>
|
||||
<!-- NOTE: path is under top_level_domains_path -->
|
||||
</top_level_domains_lists>
|
||||
```
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
cutToFirstSignificantSubdomainCustomWithWWW(URL, TLD)
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `URL` — URL. [String](../../sql-reference/data-types/string.md).
|
||||
- `TLD` — Custom TLD list name. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Part of the domain that includes top-level subdomains up to the first significant subdomain without stripping `www`.
|
||||
|
||||
Type: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```text
|
||||
┌─cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list')─┐
|
||||
│ www.foo │
|
||||
└──────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**See Also**
|
||||
|
||||
- [firstSignificantSubdomain](#firstsignificantsubdomain).
|
||||
|
||||
### firstSignificantSubdomainCustom {#firstsignificantsubdomaincustom}
|
||||
|
||||
Same as `firstSignificantSubdomain` but accept custom TLD list name.
|
||||
Returns the first significant subdomain. Accepts customs TLD list name.
|
||||
|
||||
### cutToFirstSignificantSubdomainCustomWithWWW {#cuttofirstsignificantsubdomaincustomwithwww}
|
||||
Can be useful if you need fresh TLD list or you have custom.
|
||||
|
||||
Same as `cutToFirstSignificantSubdomainWithWWW` but accept custom TLD list name.
|
||||
Configuration example:
|
||||
|
||||
```xml
|
||||
<!-- <top_level_domains_path>/var/lib/clickhouse/top_level_domains/</top_level_domains_path> -->
|
||||
<top_level_domains_lists>
|
||||
<!-- https://publicsuffix.org/list/public_suffix_list.dat -->
|
||||
<public_suffix_list>public_suffix_list.dat</public_suffix_list>
|
||||
<!-- NOTE: path is under top_level_domains_path -->
|
||||
</top_level_domains_lists>
|
||||
```
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
firstSignificantSubdomainCustom(URL, TLD)
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `URL` — URL. [String](../../sql-reference/data-types/string.md).
|
||||
- `TLD` — Custom TLD list name. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Returned value**
|
||||
|
||||
- First significant subdomain.
|
||||
|
||||
Type: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
SELECT firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list');
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```text
|
||||
┌─firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐
|
||||
│ foo │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**See Also**
|
||||
|
||||
- [firstSignificantSubdomain](#firstsignificantsubdomain).
|
||||
|
||||
### port(URL\[, default_port = 0\]) {#port}
|
||||
|
||||
|
@ -283,12 +283,10 @@ INSERT INTO test VALUES (lower('Hello')), (lower('world')), (lower('INSERT')), (
|
||||
|
||||
## input_format_tsv_empty_as_default {#settings-input-format-tsv-empty-as-default}
|
||||
|
||||
Если эта настройка включена, замените пустые поля ввода в TSV значениями по умолчанию. Для сложных выражений по умолчанию также должна быть включена настройка `input_format_defaults_for_omitted_fields`.
|
||||
Если эта настройка включена, все пустые поля во входящем TSV заменяются значениями по умолчанию. Для сложных выражений по умолчанию также должна быть включена настройка `input_format_defaults_for_omitted_fields`.
|
||||
|
||||
По умолчанию отключена.
|
||||
|
||||
Disabled by default.
|
||||
|
||||
## input_format_tsv_enum_as_number {#settings-input_format_tsv_enum_as_number}
|
||||
|
||||
Включает или отключает парсинг значений перечислений как идентификаторов перечислений для входного формата TSV.
|
||||
@ -708,7 +706,7 @@ ClickHouse использует этот параметр при чтении д
|
||||
|
||||
Установка логирования запроса.
|
||||
|
||||
Запросы, переданные в ClickHouse с этой установкой, логируются согласно правилам конфигурационного параметра сервера [query_log](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-query-log).
|
||||
Запросы, переданные в ClickHouse с этой настройкой, логируются согласно правилам конфигурационного параметра сервера [query_log](../../operations/server-configuration-parameters/settings.md#server_configuration_parameters-query-log).
|
||||
|
||||
Пример:
|
||||
|
||||
@ -1521,7 +1519,7 @@ ClickHouse генерирует исключение
|
||||
- Тип: секунды
|
||||
- Значение по умолчанию: 60 секунд
|
||||
|
||||
Управляет скоростью обнуления ошибок в распределенных таблицах. Если реплика недоступна в течение некоторого времени, накапливает 5 ошибок, а distributed_replica_error_half_life установлена на 1 секунду, то реплика считается нормальной через 3 секунды после последней ошибки.
|
||||
Управляет скоростью обнуления счетчика ошибок в распределенных таблицах. Предположим, реплика остается недоступна в течение какого-то времени, и за этот период накопилось 5 ошибок. Если настройка `distributed_replica_error_half_life` установлена в значение 1 секунда, то реплика снова будет считаться доступной через 3 секунды после последней ошибки.
|
||||
|
||||
См. также:
|
||||
|
||||
@ -1673,7 +1671,7 @@ ClickHouse генерирует исключение
|
||||
- Тип: bool
|
||||
- Значение по умолчанию: True
|
||||
|
||||
Обеспечивает параллельный анализ форматов данных с сохранением порядка. Поддерживается только для форматов TSV, TKSV, CSV и JSONEachRow.
|
||||
Включает режим, при котором входящие данные парсятся параллельно, но с сохранением исходного порядка следования. Поддерживается только для форматов TSV, TKSV, CSV и JSONEachRow.
|
||||
|
||||
## min_chunk_bytes_for_parallel_parsing {#min-chunk-bytes-for-parallel-parsing}
|
||||
|
||||
@ -1987,7 +1985,7 @@ SELECT idx, i FROM null_in WHERE i IN (1, NULL) SETTINGS transform_null_in = 1;
|
||||
|
||||
## output_format_pretty_grid_charset {#output-format-pretty-grid-charset}
|
||||
|
||||
Позволяет изменить кодировку, которая используется для печати грид-границ. Доступны следующие кодировки: UTF-8, ASCII.
|
||||
Позволяет изменить кодировку, которая используется для отрисовки таблицы при выводе результатов запросов. Доступны следующие кодировки: UTF-8, ASCII.
|
||||
|
||||
**Пример**
|
||||
|
||||
|
@ -115,6 +115,168 @@ SELECT topLevelDomain('svn+ssh://www.some.svn-hosting.com:80/repo/trunk')
|
||||
|
||||
Например, `cutToFirstSignificantSubdomain('https://news.yandex.com.tr/') = 'yandex.com.tr'`.
|
||||
|
||||
### cutToFirstSignificantSubdomainCustom {#cuttofirstsignificantsubdomaincustom}
|
||||
|
||||
Возвращает часть домена, включающую поддомены верхнего уровня до первого существенного поддомена. Принимает имя пользовательского [списка доменов верхнего уровня](https://ru.wikipedia.org/wiki/Список_доменов_верхнего_уровня).
|
||||
|
||||
Полезно, если требуется актуальный список доменов верхнего уровня или если есть пользовательский.
|
||||
|
||||
Пример конфигурации:
|
||||
|
||||
```xml
|
||||
<!-- <top_level_domains_path>/var/lib/clickhouse/top_level_domains/</top_level_domains_path> -->
|
||||
<top_level_domains_lists>
|
||||
<!-- https://publicsuffix.org/list/public_suffix_list.dat -->
|
||||
<public_suffix_list>public_suffix_list.dat</public_suffix_list>
|
||||
<!-- NOTE: path is under top_level_domains_path -->
|
||||
</top_level_domains_lists>
|
||||
```
|
||||
|
||||
**Синтаксис**
|
||||
|
||||
``` sql
|
||||
cutToFirstSignificantSubdomain(URL, TLD)
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `URL` — URL. [String](../../sql-reference/data-types/string.md).
|
||||
- `TLD` — имя пользовательского списка доменов верхнего уровня. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Возвращаемое значение**
|
||||
|
||||
- Часть домена, включающая поддомены верхнего уровня до первого существенного поддомена.
|
||||
|
||||
Тип: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Пример**
|
||||
|
||||
Запрос:
|
||||
|
||||
```sql
|
||||
SELECT cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list');
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
┌─cutToFirstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐
|
||||
│ foo.there-is-no-such-domain │
|
||||
└───────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Смотрите также**
|
||||
|
||||
- [firstSignificantSubdomain](#firstsignificantsubdomain).
|
||||
|
||||
### cutToFirstSignificantSubdomainCustomWithWWW {#cuttofirstsignificantsubdomaincustomwithwww}
|
||||
|
||||
Возвращает часть домена, включающую поддомены верхнего уровня до первого существенного поддомена, не опуская "www". Принимает имя пользовательского списка доменов верхнего уровня.
|
||||
|
||||
Полезно, если требуется актуальный список доменов верхнего уровня или если есть пользовательский.
|
||||
|
||||
Пример конфигурации:
|
||||
|
||||
```xml
|
||||
<!-- <top_level_domains_path>/var/lib/clickhouse/top_level_domains/</top_level_domains_path> -->
|
||||
<top_level_domains_lists>
|
||||
<!-- https://publicsuffix.org/list/public_suffix_list.dat -->
|
||||
<public_suffix_list>public_suffix_list.dat</public_suffix_list>
|
||||
<!-- NOTE: path is under top_level_domains_path -->
|
||||
</top_level_domains_lists>
|
||||
```
|
||||
|
||||
**Синтаксис**
|
||||
|
||||
```sql
|
||||
cutToFirstSignificantSubdomainCustomWithWWW(URL, TLD)
|
||||
```
|
||||
|
||||
**Параметры**
|
||||
|
||||
- `URL` — URL. [String](../../sql-reference/data-types/string.md).
|
||||
- `TLD` — имя пользовательского списка доменов верхнего уровня. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Возвращаемое значение**
|
||||
|
||||
- Часть домена, включающая поддомены верхнего уровня до первого существенного поддомена, без удаления `www`.
|
||||
|
||||
Тип: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Пример**
|
||||
|
||||
Запрос:
|
||||
|
||||
```sql
|
||||
SELECT cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list');
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
┌─cutToFirstSignificantSubdomainCustomWithWWW('www.foo', 'public_suffix_list')─┐
|
||||
│ www.foo │
|
||||
└──────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Смотрите также**
|
||||
|
||||
- [firstSignificantSubdomain](#firstsignificantsubdomain).
|
||||
|
||||
### firstSignificantSubdomainCustom {#firstsignificantsubdomaincustom}
|
||||
|
||||
Возвращает первый существенный поддомен. Принимает имя пользовательского списка доменов верхнего уровня.
|
||||
|
||||
Полезно, если требуется актуальный список доменов верхнего уровня или если есть пользовательский.
|
||||
|
||||
Пример конфигурации:
|
||||
|
||||
```xml
|
||||
<!-- <top_level_domains_path>/var/lib/clickhouse/top_level_domains/</top_level_domains_path> -->
|
||||
<top_level_domains_lists>
|
||||
<!-- https://publicsuffix.org/list/public_suffix_list.dat -->
|
||||
<public_suffix_list>public_suffix_list.dat</public_suffix_list>
|
||||
<!-- NOTE: path is under top_level_domains_path -->
|
||||
</top_level_domains_lists>
|
||||
```
|
||||
|
||||
**Синтаксис**
|
||||
|
||||
```sql
|
||||
firstSignificantSubdomainCustom(URL, TLD)
|
||||
```
|
||||
|
||||
**Параметры**
|
||||
|
||||
- `URL` — URL. [String](../../sql-reference/data-types/string.md).
|
||||
- `TLD` — имя пользовательского списка доменов верхнего уровня. [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Возвращаемое значение**
|
||||
|
||||
- Первый существенный поддомен.
|
||||
|
||||
Тип: [String](../../sql-reference/data-types/string.md).
|
||||
|
||||
**Пример**
|
||||
|
||||
Запрос:
|
||||
|
||||
```sql
|
||||
SELECT firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list');
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
┌─firstSignificantSubdomainCustom('bar.foo.there-is-no-such-domain', 'public_suffix_list')─┐
|
||||
│ foo │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Смотрите также**
|
||||
|
||||
- [firstSignificantSubdomain](#firstsignificantsubdomain).
|
||||
|
||||
### port(URL[, default_port = 0]) {#port}
|
||||
|
||||
Возвращает порт или значение `default_port`, если в URL-адресе нет порта (или передан невалидный URL)
|
||||
|
@ -756,7 +756,11 @@ std::optional<UInt64> Connection::checkPacket(size_t timeout_microseconds)
|
||||
Packet Connection::receivePacket(std::function<void(Poco::Net::Socket &)> async_callback)
|
||||
{
|
||||
in->setAsyncCallback(std::move(async_callback));
|
||||
SCOPE_EXIT(in->setAsyncCallback({}));
|
||||
SCOPE_EXIT({
|
||||
/// disconnect() will reset "in".
|
||||
if (in)
|
||||
in->setAsyncCallback({});
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -539,7 +539,8 @@ protected:
|
||||
* after transferring all the elements from the old halves you need to [ o x ]
|
||||
* process tail from the collision resolution chain immediately after it [ o x ]
|
||||
*/
|
||||
for (; !buf[i].isZero(*this); ++i)
|
||||
size_t new_size = grower.bufSize();
|
||||
for (; i < new_size && !buf[i].isZero(*this); ++i)
|
||||
{
|
||||
size_t updated_place_value = reinsert(buf[i], buf[i].getHash(*this));
|
||||
|
||||
|
@ -317,3 +317,51 @@ TEST(HashTable, SerializationDeserialization)
|
||||
ASSERT_EQ(convertToSet(cont), convertToSet(deserialized));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct IdentityHash
|
||||
{
|
||||
size_t operator()(T x) const { return x; }
|
||||
};
|
||||
|
||||
struct OneElementResizeGrower
|
||||
{
|
||||
/// If collision resolution chains are contiguous, we can implement erase operation by moving the elements.
|
||||
static constexpr auto performs_linear_probing_with_single_step = true;
|
||||
|
||||
static constexpr size_t initial_count = 1;
|
||||
|
||||
size_t bufSize() const { return buf_size; }
|
||||
|
||||
size_t place(size_t x) const { return x % buf_size; }
|
||||
|
||||
size_t next(size_t pos) const { return (pos + 1) % buf_size; }
|
||||
|
||||
bool overflow(size_t elems) const { return elems >= buf_size; }
|
||||
|
||||
void increaseSize() { ++buf_size; }
|
||||
|
||||
void set(size_t) { }
|
||||
|
||||
void setBufSize(size_t buf_size_) { buf_size = buf_size_; }
|
||||
|
||||
size_t buf_size = initial_count;
|
||||
};
|
||||
|
||||
TEST(HashTable, Resize)
|
||||
{
|
||||
{
|
||||
/// Test edge case if after resize all cells are resized in end of buf and will take half of
|
||||
/// hash table place.
|
||||
using HashSet = HashSet<int, IdentityHash<int>, OneElementResizeGrower>;
|
||||
HashSet cont;
|
||||
|
||||
cont.insert(3);
|
||||
cont.insert(1);
|
||||
|
||||
std::set<int> expected = {1, 3};
|
||||
std::set<int> actual = convertToSet(cont);
|
||||
|
||||
ASSERT_EQ(actual, expected);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int INCORRECT_DATA;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
std::pair<bool, size_t> fileSegmentationEngineJSONEachRowImpl(ReadBuffer & in, DB::Memory<> & memory, size_t min_chunk_size)
|
||||
@ -28,7 +29,9 @@ std::pair<bool, size_t> fileSegmentationEngineJSONEachRowImpl(ReadBuffer & in, D
|
||||
if (quotes)
|
||||
{
|
||||
pos = find_first_symbols<'\\', '"'>(pos, in.buffer().end());
|
||||
if (pos == in.buffer().end())
|
||||
if (pos > in.buffer().end())
|
||||
throw Exception("Position in buffer is out of bounds. There must be a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
else if (pos == in.buffer().end())
|
||||
continue;
|
||||
if (*pos == '\\')
|
||||
{
|
||||
@ -45,9 +48,11 @@ std::pair<bool, size_t> fileSegmentationEngineJSONEachRowImpl(ReadBuffer & in, D
|
||||
else
|
||||
{
|
||||
pos = find_first_symbols<'{', '}', '\\', '"'>(pos, in.buffer().end());
|
||||
if (pos == in.buffer().end())
|
||||
if (pos > in.buffer().end())
|
||||
throw Exception("Position in buffer is out of bounds. There must be a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
else if (pos == in.buffer().end())
|
||||
continue;
|
||||
if (*pos == '{')
|
||||
else if (*pos == '{')
|
||||
{
|
||||
++balance;
|
||||
++pos;
|
||||
|
@ -35,10 +35,10 @@ struct Memory : boost::noncopyable, Allocator
|
||||
char * m_data = nullptr;
|
||||
size_t alignment = 0;
|
||||
|
||||
Memory() {}
|
||||
Memory() = default;
|
||||
|
||||
/// If alignment != 0, then allocate memory aligned to specified value.
|
||||
Memory(size_t size_, size_t alignment_ = 0) : m_capacity(size_), m_size(m_capacity), alignment(alignment_)
|
||||
explicit Memory(size_t size_, size_t alignment_ = 0) : m_capacity(size_), m_size(m_capacity), alignment(alignment_)
|
||||
{
|
||||
alloc();
|
||||
}
|
||||
@ -140,7 +140,7 @@ protected:
|
||||
Memory<> memory;
|
||||
public:
|
||||
/// If non-nullptr 'existing_memory' is passed, then buffer will not create its own memory and will use existing_memory without ownership.
|
||||
BufferWithOwnMemory(size_t size = DBMS_DEFAULT_BUFFER_SIZE, char * existing_memory = nullptr, size_t alignment = 0)
|
||||
explicit BufferWithOwnMemory(size_t size = DBMS_DEFAULT_BUFFER_SIZE, char * existing_memory = nullptr, size_t alignment = 0)
|
||||
: Base(nullptr, 0), memory(existing_memory ? 0 : size, alignment)
|
||||
{
|
||||
Base::set(existing_memory ? existing_memory : memory.data(), size);
|
||||
|
@ -746,7 +746,7 @@ public:
|
||||
IHostContextPtr & getHostContext();
|
||||
const IHostContextPtr & getHostContext() const;
|
||||
|
||||
void initMetadataTransaction(MetadataTransactionPtr txn, bool attach_to_context = false);
|
||||
void initMetadataTransaction(MetadataTransactionPtr txn, bool attach_existing = false);
|
||||
MetadataTransactionPtr getMetadataTransaction() const;
|
||||
|
||||
struct MySQLWireContext
|
||||
|
@ -505,7 +505,6 @@ void DDLWorker::processTask(DDLTaskBase & task)
|
||||
}
|
||||
|
||||
zookeeper->create(active_node_path, {}, zkutil::CreateMode::Ephemeral);
|
||||
|
||||
}
|
||||
|
||||
if (!task.was_executed)
|
||||
|
@ -266,7 +266,7 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
ParserIdentifier id_parser;
|
||||
ParserKeyword distinct("DISTINCT");
|
||||
ParserKeyword all("ALL");
|
||||
ParserExpressionList contents(false);
|
||||
ParserExpressionList contents(false, is_table_function);
|
||||
ParserSelectWithUnionQuery select;
|
||||
ParserKeyword over("OVER");
|
||||
|
||||
@ -278,6 +278,12 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
ASTPtr expr_list_args;
|
||||
ASTPtr expr_list_params;
|
||||
|
||||
if (is_table_function)
|
||||
{
|
||||
if (ParserTableFunctionView().parse(pos, node, expected))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!id_parser.parse(pos, identifier, expected))
|
||||
return false;
|
||||
|
||||
@ -312,36 +318,6 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_distinct && !has_all)
|
||||
{
|
||||
auto old_pos = pos;
|
||||
auto maybe_an_subquery = pos->type == TokenType::OpeningRoundBracket;
|
||||
|
||||
if (select.parse(pos, query, expected))
|
||||
{
|
||||
auto & select_ast = query->as<ASTSelectWithUnionQuery &>();
|
||||
if (select_ast.list_of_selects->children.size() == 1 && maybe_an_subquery)
|
||||
{
|
||||
// It's an subquery. Bail out.
|
||||
pos = old_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos->type != TokenType::ClosingRoundBracket)
|
||||
return false;
|
||||
++pos;
|
||||
auto function_node = std::make_shared<ASTFunction>();
|
||||
tryGetIdentifierNameInto(identifier, function_node->name);
|
||||
auto expr_list_with_single_query = std::make_shared<ASTExpressionList>();
|
||||
expr_list_with_single_query->children.push_back(query);
|
||||
function_node->arguments = expr_list_with_single_query;
|
||||
function_node->children.push_back(function_node->arguments);
|
||||
node = function_node;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char * contents_begin = pos->begin;
|
||||
if (!contents.parse(pos, expr_list_args, expected))
|
||||
return false;
|
||||
@ -477,6 +453,49 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserTableFunctionView::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
ParserIdentifier id_parser;
|
||||
ParserKeyword view("VIEW");
|
||||
ParserSelectWithUnionQuery select;
|
||||
|
||||
ASTPtr identifier;
|
||||
ASTPtr query;
|
||||
|
||||
if (!view.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
if (pos->type != TokenType::OpeningRoundBracket)
|
||||
return false;
|
||||
|
||||
++pos;
|
||||
|
||||
bool maybe_an_subquery = pos->type == TokenType::OpeningRoundBracket;
|
||||
|
||||
if (!select.parse(pos, query, expected))
|
||||
return false;
|
||||
|
||||
auto & select_ast = query->as<ASTSelectWithUnionQuery &>();
|
||||
if (select_ast.list_of_selects->children.size() == 1 && maybe_an_subquery)
|
||||
{
|
||||
// It's an subquery. Bail out.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pos->type != TokenType::ClosingRoundBracket)
|
||||
return false;
|
||||
++pos;
|
||||
auto function_node = std::make_shared<ASTFunction>();
|
||||
tryGetIdentifierNameInto(identifier, function_node->name);
|
||||
auto expr_list_with_single_query = std::make_shared<ASTExpressionList>();
|
||||
expr_list_with_single_query->children.push_back(query);
|
||||
function_node->name = "view";
|
||||
function_node->arguments = expr_list_with_single_query;
|
||||
function_node->children.push_back(function_node->arguments);
|
||||
node = function_node;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserWindowReference::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
ASTFunction * function = dynamic_cast<ASTFunction *>(node.get());
|
||||
|
@ -149,11 +149,25 @@ protected:
|
||||
class ParserFunction : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserFunction(bool allow_function_parameters_ = true) : allow_function_parameters(allow_function_parameters_) {}
|
||||
ParserFunction(bool allow_function_parameters_ = true, bool is_table_function_ = false)
|
||||
: allow_function_parameters(allow_function_parameters_), is_table_function(is_table_function_)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
const char * getName() const override { return "function"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
bool allow_function_parameters;
|
||||
bool is_table_function;
|
||||
};
|
||||
|
||||
// A special function parser for view table function.
|
||||
// It parses an SELECT query as its argument and doesn't support getColumnName().
|
||||
class ParserTableFunctionView : public IParserBase
|
||||
{
|
||||
protected:
|
||||
const char * getName() const override { return "function"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
};
|
||||
|
||||
// Window reference (the thing that goes after OVER) for window function.
|
||||
|
@ -468,6 +468,14 @@ bool ParserLambdaExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expe
|
||||
}
|
||||
|
||||
|
||||
bool ParserTableFunctionExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
if (ParserTableFunctionView().parse(pos, node, expected))
|
||||
return true;
|
||||
return elem_parser.parse(pos, node, expected);
|
||||
}
|
||||
|
||||
|
||||
bool ParserPrefixUnaryOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
/// try to find any of the valid operators
|
||||
@ -570,9 +578,10 @@ bool ParserTupleElementExpression::parseImpl(Pos & pos, ASTPtr & node, Expected
|
||||
}
|
||||
|
||||
|
||||
ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword)
|
||||
: impl(std::make_unique<ParserWithOptionalAlias>(std::make_unique<ParserExpression>(),
|
||||
allow_alias_without_as_keyword))
|
||||
ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword, bool is_table_function)
|
||||
: impl(std::make_unique<ParserWithOptionalAlias>(
|
||||
is_table_function ? ParserPtr(std::make_unique<ParserTableFunctionExpression>()) : ParserPtr(std::make_unique<ParserExpression>()),
|
||||
allow_alias_without_as_keyword))
|
||||
{
|
||||
}
|
||||
|
||||
@ -580,7 +589,7 @@ ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_
|
||||
bool ParserExpressionList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
return ParserList(
|
||||
std::make_unique<ParserExpressionWithOptionalAlias>(allow_alias_without_as_keyword),
|
||||
std::make_unique<ParserExpressionWithOptionalAlias>(allow_alias_without_as_keyword, is_table_function),
|
||||
std::make_unique<ParserToken>(TokenType::Comma))
|
||||
.parse(pos, node, expected);
|
||||
}
|
||||
|
@ -436,13 +436,26 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
// It's used to parse expressions in table function.
|
||||
class ParserTableFunctionExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserLambdaExpression elem_parser;
|
||||
|
||||
protected:
|
||||
const char * getName() const override { return "table function expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
};
|
||||
|
||||
|
||||
using ParserExpression = ParserLambdaExpression;
|
||||
|
||||
|
||||
class ParserExpressionWithOptionalAlias : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword);
|
||||
explicit ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword, bool is_table_function = false);
|
||||
protected:
|
||||
ParserPtr impl;
|
||||
|
||||
@ -459,11 +472,12 @@ protected:
|
||||
class ParserExpressionList : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserExpressionList(bool allow_alias_without_as_keyword_)
|
||||
: allow_alias_without_as_keyword(allow_alias_without_as_keyword_) {}
|
||||
explicit ParserExpressionList(bool allow_alias_without_as_keyword_, bool is_table_function_ = false)
|
||||
: allow_alias_without_as_keyword(allow_alias_without_as_keyword_), is_table_function(is_table_function_) {}
|
||||
|
||||
protected:
|
||||
bool allow_alias_without_as_keyword;
|
||||
bool is_table_function; // This expression list is used by a table function
|
||||
|
||||
const char * getName() const override { return "list of expressions"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
@ -473,7 +487,7 @@ protected:
|
||||
class ParserNotEmptyExpressionList : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserNotEmptyExpressionList(bool allow_alias_without_as_keyword)
|
||||
explicit ParserNotEmptyExpressionList(bool allow_alias_without_as_keyword)
|
||||
: nested_parser(allow_alias_without_as_keyword) {}
|
||||
private:
|
||||
ParserExpressionList nested_parser;
|
||||
|
@ -22,7 +22,7 @@ bool ParserTableExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
||||
auto res = std::make_shared<ASTTableExpression>();
|
||||
|
||||
if (!ParserWithOptionalAlias(std::make_unique<ParserSubquery>(), true).parse(pos, res->subquery, expected)
|
||||
&& !ParserWithOptionalAlias(std::make_unique<ParserFunction>(), true).parse(pos, res->table_function, expected)
|
||||
&& !ParserWithOptionalAlias(std::make_unique<ParserFunction>(true, true), true).parse(pos, res->table_function, expected)
|
||||
&& !ParserWithOptionalAlias(std::make_unique<ParserCompoundIdentifier>(false, true), true).parse(pos, res->database_and_table_name, expected))
|
||||
return false;
|
||||
|
||||
|
@ -15,6 +15,7 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int INCORRECT_DATA;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@ -436,9 +437,11 @@ static std::pair<bool, size_t> fileSegmentationEngineCSVImpl(ReadBuffer & in, DB
|
||||
if (quotes)
|
||||
{
|
||||
pos = find_first_symbols<'"'>(pos, in.buffer().end());
|
||||
if (pos == in.buffer().end())
|
||||
if (pos > in.buffer().end())
|
||||
throw Exception("Position in buffer is out of bounds. There must be a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
else if (pos == in.buffer().end())
|
||||
continue;
|
||||
if (*pos == '"')
|
||||
else if (*pos == '"')
|
||||
{
|
||||
++pos;
|
||||
if (loadAtPosition(in, memory, pos) && *pos == '"')
|
||||
@ -450,9 +453,11 @@ static std::pair<bool, size_t> fileSegmentationEngineCSVImpl(ReadBuffer & in, DB
|
||||
else
|
||||
{
|
||||
pos = find_first_symbols<'"', '\r', '\n'>(pos, in.buffer().end());
|
||||
if (pos == in.buffer().end())
|
||||
if (pos > in.buffer().end())
|
||||
throw Exception("Position in buffer is out of bounds. There must be a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
else if (pos == in.buffer().end())
|
||||
continue;
|
||||
if (*pos == '"')
|
||||
else if (*pos == '"')
|
||||
{
|
||||
quotes = true;
|
||||
++pos;
|
||||
|
@ -11,6 +11,7 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int INCORRECT_DATA;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
RegexpRowInputFormat::RegexpRowInputFormat(
|
||||
@ -182,7 +183,9 @@ static std::pair<bool, size_t> fileSegmentationEngineRegexpImpl(ReadBuffer & in,
|
||||
while (loadAtPosition(in, memory, pos) && need_more_data)
|
||||
{
|
||||
pos = find_first_symbols<'\n', '\r'>(pos, in.buffer().end());
|
||||
if (pos == in.buffer().end())
|
||||
if (pos > in.buffer().end())
|
||||
throw Exception("Position in buffer is out of bounds. There must be a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
else if (pos == in.buffer().end())
|
||||
continue;
|
||||
|
||||
// Support DOS-style newline ("\r\n")
|
||||
|
@ -15,6 +15,7 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int INCORRECT_DATA;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@ -433,10 +434,11 @@ static std::pair<bool, size_t> fileSegmentationEngineTabSeparatedImpl(ReadBuffer
|
||||
{
|
||||
pos = find_first_symbols<'\\', '\r', '\n'>(pos, in.buffer().end());
|
||||
|
||||
if (pos == in.buffer().end())
|
||||
if (pos > in.buffer().end())
|
||||
throw Exception("Position in buffer is out of bounds. There must be a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
else if (pos == in.buffer().end())
|
||||
continue;
|
||||
|
||||
if (*pos == '\\')
|
||||
else if (*pos == '\\')
|
||||
{
|
||||
++pos;
|
||||
if (loadAtPosition(in, memory, pos))
|
||||
|
@ -753,7 +753,7 @@ void StorageReplicatedMergeTree::drop()
|
||||
auto zookeeper = global_context.getZooKeeper();
|
||||
|
||||
/// If probably there is metadata in ZooKeeper, we don't allow to drop the table.
|
||||
if (is_readonly || !zookeeper)
|
||||
if (!zookeeper)
|
||||
throw Exception("Can't drop readonly replicated table (need to drop data in ZooKeeper as well)", ErrorCodes::TABLE_IS_READ_ONLY);
|
||||
|
||||
shutdown();
|
||||
|
@ -22,12 +22,12 @@ DROP TABLE IF EXISTS test_r1;
|
||||
DROP TABLE IF EXISTS test_r2;
|
||||
|
||||
CREATE TABLE test_r1 (x UInt64, "\\" String DEFAULT '\r\n\t\\' || '
|
||||
') ENGINE = ReplicatedMergeTree('/clickhouse/test', 'r1') ORDER BY "\\";
|
||||
') ENGINE = ReplicatedMergeTree('/clickhouse/test_01669', 'r1') ORDER BY "\\";
|
||||
|
||||
INSERT INTO test_r1 ("\\") VALUES ('\\');
|
||||
|
||||
CREATE TABLE test_r2 (x UInt64, "\\" String DEFAULT '\r\n\t\\' || '
|
||||
') ENGINE = ReplicatedMergeTree('/clickhouse/test', 'r2') ORDER BY "\\";
|
||||
') ENGINE = ReplicatedMergeTree('/clickhouse/test_01669', 'r2') ORDER BY "\\";
|
||||
|
||||
SYSTEM SYNC REPLICA test_r2;
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
SELECT view(SELECT 1); -- { clientError 62 }
|
@ -1,6 +1,6 @@
|
||||
100
|
||||
6410
|
||||
6410
|
||||
25323
|
||||
100
|
||||
25323
|
||||
1774655
|
||||
100
|
||||
1774655
|
||||
|
@ -6,15 +6,15 @@ CREATE DICTIONARY db_dict.cache_hits
|
||||
PRIMARY KEY WatchID
|
||||
SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'hits' PASSWORD '' DB 'test'))
|
||||
LIFETIME(MIN 300 MAX 600)
|
||||
LAYOUT(CACHE(SIZE_IN_CELLS 100000 QUERY_WAIT_TIMEOUT_MILLISECONDS 600000));
|
||||
LAYOUT(CACHE(SIZE_IN_CELLS 100 QUERY_WAIT_TIMEOUT_MILLISECONDS 600000));
|
||||
|
||||
SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 1400 == 0);
|
||||
SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 1400 == 0 LIMIT 100);
|
||||
SELECT count() from test.hits PREWHERE WatchID % 1400 == 0;
|
||||
|
||||
SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 350 == 0);
|
||||
SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 350 == 0 LIMIT 100);
|
||||
SELECT count() from test.hits PREWHERE WatchID % 350 == 0;
|
||||
|
||||
SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 5 == 0);
|
||||
SELECT sum(flag) FROM (SELECT dictHas('db_dict.cache_hits', toUInt64(WatchID)) as flag FROM test.hits PREWHERE WatchID % 5 == 0 LIMIT 100);
|
||||
SELECT count() from test.hits PREWHERE WatchID % 5 == 0;
|
||||
|
||||
DROP DICTIONARY IF EXISTS db_dict.cache_hits;
|
||||
|
@ -726,6 +726,7 @@
|
||||
"01676_dictget_in_default_expression",
|
||||
"01715_background_checker_blather_zookeeper",
|
||||
"01700_system_zookeeper_path_in",
|
||||
"01669_columns_declaration_serde",
|
||||
"attach",
|
||||
"ddl_dictionaries",
|
||||
"dictionary",
|
||||
|
Loading…
Reference in New Issue
Block a user