mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-01 20:12:02 +00:00
Merge remote-tracking branch 'refs/remotes/origin/master' into base64encode-tests
This commit is contained in:
commit
2355035207
@ -13,5 +13,4 @@ rules:
|
||||
level: warning
|
||||
comments:
|
||||
min-spaces-from-content: 1
|
||||
document-start:
|
||||
present: false
|
||||
document-start: disable
|
||||
|
@ -34,7 +34,7 @@
|
||||
* Add `_time` virtual column to file alike storages (s3/file/hdfs/url/azureBlobStorage). [#64947](https://github.com/ClickHouse/ClickHouse/pull/64947) ([Ilya Golshtein](https://github.com/ilejn)).
|
||||
* Introduced new functions `base64URLEncode`, `base64URLDecode` and `tryBase64URLDecode`. [#64991](https://github.com/ClickHouse/ClickHouse/pull/64991) ([Mikhail Gorshkov](https://github.com/mgorshkov)).
|
||||
* Add new function `editDistanceUTF8`, which calculates the [edit distance](https://en.wikipedia.org/wiki/Edit_distance) between two UTF8 strings. [#65269](https://github.com/ClickHouse/ClickHouse/pull/65269) ([LiuNeng](https://github.com/liuneng1994)).
|
||||
* Add `http_response_headers` setting to support custom response headers in custom HTTP handlers. [#63562](https://github.com/ClickHouse/ClickHouse/pull/63562) ([Grigorii](https://github.com/GSokol)).
|
||||
* Add `http_response_headers` configuration to support custom response headers in custom HTTP handlers. [#63562](https://github.com/ClickHouse/ClickHouse/pull/63562) ([Grigorii](https://github.com/GSokol)).
|
||||
* Added a new table function `loop` to support returning query results in an infinite loop. [#63452](https://github.com/ClickHouse/ClickHouse/pull/63452) ([Sariel](https://github.com/sarielwxm)). This is useful for testing.
|
||||
* Introduced two additional columns in the `system.query_log`: `used_privileges` and `missing_privileges`. `used_privileges` is populated with the privileges that were checked during query execution, and `missing_privileges` contains required privileges that are missing. [#64597](https://github.com/ClickHouse/ClickHouse/pull/64597) ([Alexey Katsman](https://github.com/alexkats)).
|
||||
* Added a setting `output_format_pretty_display_footer_column_names` which when enabled displays column names at the end of the table for long tables (50 rows by default), with the threshold value for minimum number of rows controlled by `output_format_pretty_display_footer_column_names_min_rows`. [#65144](https://github.com/ClickHouse/ClickHouse/pull/65144) ([Shaun Struwig](https://github.com/Blargian)).
|
||||
|
@ -235,8 +235,6 @@ namespace Net
|
||||
/// Note that simply closing a socket is not sufficient
|
||||
/// to be able to re-use it again.
|
||||
|
||||
Poco::Timespan getMaxTimeout();
|
||||
|
||||
private:
|
||||
SecureSocketImpl(const SecureSocketImpl &);
|
||||
SecureSocketImpl & operator=(const SecureSocketImpl &);
|
||||
@ -250,6 +248,9 @@ namespace Net
|
||||
Session::Ptr _pSession;
|
||||
|
||||
friend class SecureStreamSocketImpl;
|
||||
|
||||
Poco::Timespan getMaxTimeoutOrLimit();
|
||||
//// Return max(send, receive) if non zero, otherwise maximum timeout
|
||||
};
|
||||
|
||||
|
||||
|
@ -199,7 +199,7 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
|
||||
if (performHandshake && _pSocket->getBlocking())
|
||||
{
|
||||
int ret;
|
||||
Poco::Timespan remaining_time = getMaxTimeout();
|
||||
Poco::Timespan remaining_time = getMaxTimeoutOrLimit();
|
||||
do
|
||||
{
|
||||
RemainingTimeCounter counter(remaining_time);
|
||||
@ -302,7 +302,7 @@ int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
|
||||
return rc;
|
||||
}
|
||||
|
||||
Poco::Timespan remaining_time = getMaxTimeout();
|
||||
Poco::Timespan remaining_time = getMaxTimeoutOrLimit();
|
||||
do
|
||||
{
|
||||
RemainingTimeCounter counter(remaining_time);
|
||||
@ -338,7 +338,7 @@ int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
|
||||
return rc;
|
||||
}
|
||||
|
||||
Poco::Timespan remaining_time = getMaxTimeout();
|
||||
Poco::Timespan remaining_time = getMaxTimeoutOrLimit();
|
||||
do
|
||||
{
|
||||
/// SSL record may consist of several TCP packets,
|
||||
@ -372,7 +372,7 @@ int SecureSocketImpl::completeHandshake()
|
||||
poco_check_ptr (_pSSL);
|
||||
|
||||
int rc;
|
||||
Poco::Timespan remaining_time = getMaxTimeout();
|
||||
Poco::Timespan remaining_time = getMaxTimeoutOrLimit();
|
||||
do
|
||||
{
|
||||
RemainingTimeCounter counter(remaining_time);
|
||||
@ -453,18 +453,29 @@ X509* SecureSocketImpl::peerCertificate() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
Poco::Timespan SecureSocketImpl::getMaxTimeout()
|
||||
Poco::Timespan SecureSocketImpl::getMaxTimeoutOrLimit()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
Poco::Timespan remaining_time = _pSocket->getReceiveTimeout();
|
||||
Poco::Timespan send_timeout = _pSocket->getSendTimeout();
|
||||
if (remaining_time < send_timeout)
|
||||
remaining_time = send_timeout;
|
||||
/// zero SO_SNDTIMEO/SO_RCVTIMEO works as no timeout, let's replicate this
|
||||
///
|
||||
/// NOTE: we cannot use INT64_MAX (std::numeric_limits<Poco::Timespan::TimeDiff>::max()),
|
||||
/// since it will be later passed to poll() which accept int timeout, and
|
||||
/// even though poll() accepts milliseconds and Timespan() accepts
|
||||
/// microseconds, let's use smaller maximum value just to avoid some possible
|
||||
/// issues, this should be enough anyway (it is ~24 days).
|
||||
if (remaining_time == 0)
|
||||
remaining_time = Poco::Timespan(std::numeric_limits<int>::max());
|
||||
return remaining_time;
|
||||
}
|
||||
|
||||
bool SecureSocketImpl::mustRetry(int rc, Poco::Timespan& remaining_time)
|
||||
{
|
||||
if (remaining_time == 0)
|
||||
return false;
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
if (rc <= 0)
|
||||
{
|
||||
@ -475,9 +486,7 @@ bool SecureSocketImpl::mustRetry(int rc, Poco::Timespan& remaining_time)
|
||||
case SSL_ERROR_WANT_READ:
|
||||
if (_pSocket->getBlocking())
|
||||
{
|
||||
/// Level-triggered mode of epoll_wait is used, so if SSL_read don't read all available data from socket,
|
||||
/// epoll_wait returns true without waiting for new data even if remaining_time == 0
|
||||
if (_pSocket->pollImpl(remaining_time, Poco::Net::Socket::SELECT_READ) && remaining_time != 0)
|
||||
if (_pSocket->pollImpl(remaining_time, Poco::Net::Socket::SELECT_READ))
|
||||
return true;
|
||||
else
|
||||
throw Poco::TimeoutException();
|
||||
@ -486,13 +495,15 @@ bool SecureSocketImpl::mustRetry(int rc, Poco::Timespan& remaining_time)
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
if (_pSocket->getBlocking())
|
||||
{
|
||||
/// The same as for SSL_ERROR_WANT_READ
|
||||
if (_pSocket->pollImpl(remaining_time, Poco::Net::Socket::SELECT_WRITE) && remaining_time != 0)
|
||||
if (_pSocket->pollImpl(remaining_time, Poco::Net::Socket::SELECT_WRITE))
|
||||
return true;
|
||||
else
|
||||
throw Poco::TimeoutException();
|
||||
}
|
||||
break;
|
||||
/// NOTE: POCO_EINTR is the same as SSL_ERROR_WANT_READ (at least in
|
||||
/// OpenSSL), so this likely dead code, but let's leave it for
|
||||
/// compatibility with other implementations
|
||||
case SSL_ERROR_SYSCALL:
|
||||
return socketError == POCO_EAGAIN || socketError == POCO_EINTR;
|
||||
default:
|
||||
|
@ -253,7 +253,7 @@ function run_tests()
|
||||
try_run_with_retry 10 clickhouse-client -q "insert into system.zookeeper (name, path, value) values ('auxiliary_zookeeper2', '/test/chroot/', '')"
|
||||
|
||||
set +e
|
||||
clickhouse-test --testname --shard --zookeeper --check-zookeeper-session --hung-check --print-time \
|
||||
timeout -s TERM --preserve-status 120m clickhouse-test --testname --shard --zookeeper --check-zookeeper-session --hung-check --print-time \
|
||||
--no-drop-if-fail --test-runs "$NUM_TRIES" "${ADDITIONAL_OPTIONS[@]}" 2>&1 \
|
||||
| ts '%Y-%m-%d %H:%M:%S' \
|
||||
| tee -a test_output/test_result.txt
|
||||
|
@ -6,23 +6,30 @@ import SelfManaged from '@site/docs/en/_snippets/_self_managed_only_no_roadmap.m
|
||||
|
||||
<SelfManaged />
|
||||
|
||||
[SSL 'strict' option](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) enables mandatory certificate validation for the incoming connections. In this case, only connections with trusted certificates can be established. Connections with untrusted certificates will be rejected. Thus, certificate validation allows to uniquely authenticate an incoming connection. `Common Name` field of the certificate is used to identify connected user. This allows to associate multiple certificates with the same user. Additionally, reissuing and revoking of the certificates does not affect the ClickHouse configuration.
|
||||
[SSL 'strict' option](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) enables mandatory certificate validation for the incoming connections. In this case, only connections with trusted certificates can be established. Connections with untrusted certificates will be rejected. Thus, certificate validation allows to uniquely authenticate an incoming connection. `Common Name` or `subjectAltName extension` field of the certificate is used to identify the connected user. This allows to associate multiple certificates with the same user. Additionally, reissuing and revoking of the certificates does not affect the ClickHouse configuration.
|
||||
|
||||
To enable SSL certificate authentication, a list of `Common Name`'s for each ClickHouse user must be specified in the settings file `users.xml `:
|
||||
To enable SSL certificate authentication, a list of `Common Name`'s or `Subject Alt Name`'s for each ClickHouse user must be specified in the settings file `users.xml `:
|
||||
|
||||
**Example**
|
||||
```xml
|
||||
<clickhouse>
|
||||
<!- ... -->
|
||||
<users>
|
||||
<user_name>
|
||||
<user_name_1>
|
||||
<ssl_certificates>
|
||||
<common_name>host.domain.com:example_user</common_name>
|
||||
<common_name>host.domain.com:example_user_dev</common_name>
|
||||
<!-- More names -->
|
||||
</ssl_certificates>
|
||||
<!-- Other settings -->
|
||||
</user_name>
|
||||
</user_name_1>
|
||||
<user_name_2>
|
||||
<ssl_certificates>
|
||||
<subject_alt_name>DNS:host.domain.com</subject_alt_name>
|
||||
<!-- More names -->
|
||||
</ssl_certificates>
|
||||
<!-- Other settings -->
|
||||
</user_name_2>
|
||||
</users>
|
||||
</clickhouse>
|
||||
```
|
||||
|
@ -1,24 +1,20 @@
|
||||
---
|
||||
slug: /en/sql-reference/data-types/json
|
||||
slug: /en/sql-reference/data-types/object-data-type
|
||||
sidebar_position: 26
|
||||
sidebar_label: JSON
|
||||
sidebar_label: Object Data Type
|
||||
keywords: [object, data type]
|
||||
---
|
||||
|
||||
# JSON
|
||||
# Object Data Type
|
||||
|
||||
:::note
|
||||
This feature is experimental and is not production-ready. If you need to work with JSON documents, consider using [this guide](/docs/en/integrations/data-ingestion/data-formats/json.md) instead.
|
||||
This feature is not production-ready and is now deprecated. If you need to work with JSON documents, consider using [this guide](/docs/en/integrations/data-ingestion/data-formats/json) instead. A new implementation to support JSON object is in progress and can be tracked [here](https://github.com/ClickHouse/ClickHouse/issues/54864)
|
||||
:::
|
||||
|
||||
Stores JavaScript Object Notation (JSON) documents in a single column.
|
||||
|
||||
`JSON` is an alias for `Object('json')`.
|
||||
|
||||
:::note
|
||||
The JSON data type is an obsolete feature. Do not use it.
|
||||
If you want to use it, set `allow_experimental_object_type = 1`.
|
||||
:::
|
||||
|
||||
## Example
|
||||
|
||||
**Example 1**
|
||||
@ -49,7 +45,7 @@ SELECT o.a, o.b.c, o.b.d[3] FROM json
|
||||
|
||||
**Example 2**
|
||||
|
||||
To be able to create an ordered `MergeTree` family table the sorting key has to be extracted into its column. For example, to insert a file of compressed HTTP access logs in JSON format:
|
||||
To be able to create an ordered `MergeTree` family table, the sorting key has to be extracted into its column. For example, to insert a file of compressed HTTP access logs in JSON format:
|
||||
|
||||
```sql
|
||||
CREATE TABLE logs
|
||||
@ -69,7 +65,7 @@ FROM file('access.json.gz', JSONAsString)
|
||||
|
||||
## Displaying JSON columns
|
||||
|
||||
When displaying a `JSON` column ClickHouse only shows the field values by default (because internally, it is represented as a tuple). You can display the field names as well by setting `output_format_json_named_tuples_as_objects = 1`:
|
||||
When displaying a `JSON` column, ClickHouse only shows the field values by default (because internally, it is represented as a tuple). You can also display the field names by setting `output_format_json_named_tuples_as_objects = 1`:
|
||||
|
||||
```sql
|
||||
SET output_format_json_named_tuples_as_objects = 1
|
||||
@ -83,4 +79,5 @@ SELECT * FROM json FORMAT JSONEachRow
|
||||
|
||||
## Related Content
|
||||
|
||||
- [Using JSON in ClickHouse](/docs/en/integrations/data-formats/json)
|
||||
- [Getting Data Into ClickHouse - Part 2 - A JSON detour](https://clickhouse.com/blog/getting-data-into-clickhouse-part-2-json)
|
||||
|
@ -173,7 +173,7 @@ See function [substring](string-functions.md#substring).
|
||||
|
||||
## bitTest
|
||||
|
||||
Takes any integer and converts it into [binary form](https://en.wikipedia.org/wiki/Binary_number), returns the value of a bit at specified position. The countdown starts from 0 from the right to the left.
|
||||
Takes any integer and converts it into [binary form](https://en.wikipedia.org/wiki/Binary_number), returns the value of a bit at specified position. Counting is right-to-left, starting at 0.
|
||||
|
||||
**Syntax**
|
||||
|
||||
@ -226,7 +226,7 @@ Result:
|
||||
|
||||
## bitTestAll
|
||||
|
||||
Returns result of [logical conjuction](https://en.wikipedia.org/wiki/Logical_conjunction) (AND operator) of all bits at given positions. The countdown starts from 0 from the right to the left.
|
||||
Returns result of [logical conjuction](https://en.wikipedia.org/wiki/Logical_conjunction) (AND operator) of all bits at given positions. Counting is right-to-left, starting at 0.
|
||||
|
||||
The conjuction for bit-wise operations:
|
||||
|
||||
@ -289,7 +289,7 @@ Result:
|
||||
|
||||
## bitTestAny
|
||||
|
||||
Returns result of [logical disjunction](https://en.wikipedia.org/wiki/Logical_disjunction) (OR operator) of all bits at given positions. The countdown starts from 0 from the right to the left.
|
||||
Returns result of [logical disjunction](https://en.wikipedia.org/wiki/Logical_disjunction) (OR operator) of all bits at given positions. Counting is right-to-left, starting at 0.
|
||||
|
||||
The disjunction for bit-wise operations:
|
||||
|
||||
|
@ -3860,3 +3860,138 @@ Result:
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## transactionID
|
||||
|
||||
Returns the ID of a [transaction](https://clickhouse.com/docs/en/guides/developer/transactional#transactions-commit-and-rollback).
|
||||
|
||||
:::note
|
||||
This function is part of an experimental feature set. Enable experimental transaction support by adding this setting to your configuration:
|
||||
|
||||
```
|
||||
<clickhouse>
|
||||
<allow_experimental_transactions>1</allow_experimental_transactions>
|
||||
</clickhouse>
|
||||
```
|
||||
|
||||
For more information see the page [Transactional (ACID) support](https://clickhouse.com/docs/en/guides/developer/transactional#transactions-commit-and-rollback).
|
||||
:::
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
transactionID()
|
||||
```
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Returns a tuple consisting of `start_csn`, `local_tid` and `host_id`. [Tuple](../data-types/tuple.md).
|
||||
|
||||
- `start_csn`: Global sequential number, the newest commit timestamp that was seen when this transaction began. [UInt64](../data-types/int-uint.md).
|
||||
- `local_tid`: Local sequential number that is unique for each transaction started by this host within a specific start_csn. [UInt64](../data-types/int-uint.md).
|
||||
- `host_id`: UUID of the host that has started this transaction. [UUID](../data-types/uuid.md).
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
BEGIN TRANSACTION;
|
||||
SELECT transactionID();
|
||||
ROLLBACK;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─transactionID()────────────────────────────────┐
|
||||
│ (32,34,'0ee8b069-f2bb-4748-9eae-069c85b5252b') │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## transactionLatestSnapshot
|
||||
|
||||
Returns the newest snapshot (Commit Sequence Number) of a [transaction](https://clickhouse.com/docs/en/guides/developer/transactional#transactions-commit-and-rollback) that is available for reading.
|
||||
|
||||
:::note
|
||||
This function is part of an experimental feature set. Enable experimental transaction support by adding this setting to your configuration:
|
||||
|
||||
```
|
||||
<clickhouse>
|
||||
<allow_experimental_transactions>1</allow_experimental_transactions>
|
||||
</clickhouse>
|
||||
```
|
||||
|
||||
For more information see the page [Transactional (ACID) support](https://clickhouse.com/docs/en/guides/developer/transactional#transactions-commit-and-rollback).
|
||||
:::
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
transactionLatestSnapshot()
|
||||
```
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Returns the latest snapshot (CSN) of a transaction. [UInt64](../data-types/int-uint.md)
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
BEGIN TRANSACTION;
|
||||
SELECT transactionLatestSnapshot();
|
||||
ROLLBACK;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─transactionLatestSnapshot()─┐
|
||||
│ 32 │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
## transactionOldestSnapshot
|
||||
|
||||
Returns the oldest snapshot (Commit Sequence Number) that is visible for some running [transaction](https://clickhouse.com/docs/en/guides/developer/transactional#transactions-commit-and-rollback).
|
||||
|
||||
:::note
|
||||
This function is part of an experimental feature set. Enable experimental transaction support by adding this setting to your configuration:
|
||||
|
||||
```
|
||||
<clickhouse>
|
||||
<allow_experimental_transactions>1</allow_experimental_transactions>
|
||||
</clickhouse>
|
||||
```
|
||||
|
||||
For more information see the page [Transactional (ACID) support](https://clickhouse.com/docs/en/guides/developer/transactional#transactions-commit-and-rollback).
|
||||
:::
|
||||
|
||||
**Syntax**
|
||||
|
||||
```sql
|
||||
transactionOldestSnapshot()
|
||||
```
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Returns the oldest snapshot (CSN) of a transaction. [UInt64](../data-types/int-uint.md)
|
||||
|
||||
**Example**
|
||||
|
||||
Query:
|
||||
|
||||
```sql
|
||||
BEGIN TRANSACTION;
|
||||
SELECT transactionLatestSnapshot();
|
||||
ROLLBACK;
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```response
|
||||
┌─transactionOldestSnapshot()─┐
|
||||
│ 32 │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
@ -12,7 +12,7 @@ Syntax:
|
||||
``` sql
|
||||
ALTER USER [IF EXISTS] name1 [ON CLUSTER cluster_name1] [RENAME TO new_name1]
|
||||
[, name2 [ON CLUSTER cluster_name2] [RENAME TO new_name2] ...]
|
||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name'}]
|
||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'}]
|
||||
[[ADD | DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||
[VALID UNTIL datetime]
|
||||
[DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
|
||||
|
@ -12,7 +12,7 @@ Syntax:
|
||||
``` sql
|
||||
CREATE USER [IF NOT EXISTS | OR REPLACE] name1 [ON CLUSTER cluster_name1]
|
||||
[, name2 [ON CLUSTER cluster_name2] ...]
|
||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'} | {WITH http SERVER 'server_name' [SCHEME 'Basic']}]
|
||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'} | {WITH http SERVER 'server_name' [SCHEME 'Basic']}]
|
||||
[HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||
[VALID UNTIL datetime]
|
||||
[IN access_storage_type]
|
||||
|
@ -269,9 +269,9 @@ FROM s3(
|
||||
|
||||
## Virtual Columns {#virtual-columns}
|
||||
|
||||
- `_path` — Path to the file. Type: `LowCardinalty(String)`.
|
||||
- `_file` — Name of the file. Type: `LowCardinalty(String)`.
|
||||
- `_size` — Size of the file in bytes. Type: `Nullable(UInt64)`. If the file size is unknown, the value is `NULL`.
|
||||
- `_path` — Path to the file. Type: `LowCardinalty(String)`. In case of archive, shows path in a format: "{path_to_archive}::{path_to_file_inside_archive}"
|
||||
- `_file` — Name of the file. Type: `LowCardinalty(String)`. In case of archive shows name of the file inside the archive.
|
||||
- `_size` — Size of the file in bytes. Type: `Nullable(UInt64)`. If the file size is unknown, the value is `NULL`. In case of archive shows uncompressed file size of the file inside the archive.
|
||||
- `_time` — Last modified time of the file. Type: `Nullable(DateTime)`. If the time is unknown, the value is `NULL`.
|
||||
|
||||
## Storage Settings {#storage-settings}
|
||||
|
@ -80,8 +80,8 @@ These functions can be used only as a window function.
|
||||
- `nth_value(x, offset)` - Return the first non-NULL value evaluated against the nth row (offset) in its ordered frame.
|
||||
- `rank()` - Rank the current row within its partition with gaps.
|
||||
- `dense_rank()` - Rank the current row within its partition without gaps.
|
||||
- `lagInFrame(x)` - Return a value evaluated at the row that is at a specified physical offset row before the current row within the ordered frame.
|
||||
- `leadInFrame(x)` - Return a value evaluated at the row that is offset rows after the current row within the ordered frame.
|
||||
- `lagInFrame(x[, offset[, default]])` - Return a value evaluated at the row that is at a specified physical offset row before the current row within the ordered frame. The offset parameter, if not specified, defaults to 1, meaning it will fetch the value from the next row. If the calculated row exceeds the boundaries of the window frame, the specified default value is returned.
|
||||
- `leadInFrame(x[, offset[, default]])` - Return a value evaluated at the row that is offset rows after the current row within the ordered frame. If offset is not provided, it defaults to 1. If the offset leads to a position outside the window frame, the specified default value is used.
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -3,23 +3,30 @@ slug: /ru/operations/external-authenticators/ssl-x509
|
||||
---
|
||||
# Аутентификация по сертификату SSL X.509 {#ssl-external-authentication}
|
||||
|
||||
[Опция 'strict'](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) включает обязательную проверку сертификатов входящих соединений в библиотеке `SSL`. В этом случае могут быть установлены только соединения, представившие действительный сертификат. Соединения с недоверенными сертификатами будут отвергнуты. Таким образом, проверка сертификата позволяет однозначно аутентифицировать входящее соединение. Идентификация пользователя осуществляется по полю `Common Name` сертификата. Это позволяет ассоциировать несколько сертификатов с одним и тем же пользователем. Дополнительно, перевыпуск и отзыв сертификата не требуют изменения конфигурации ClickHouse.
|
||||
[Опция 'strict'](../server-configuration-parameters/settings.md#server_configuration_parameters-openssl) включает обязательную проверку сертификатов входящих соединений в библиотеке `SSL`. В этом случае могут быть установлены только соединения, представившие действительный сертификат. Соединения с недоверенными сертификатами будут отвергнуты. Таким образом, проверка сертификата позволяет однозначно аутентифицировать входящее соединение. Идентификация пользователя осуществляется по полю `Common Name` или `subjectAltName` сертификата. Это позволяет ассоциировать несколько сертификатов с одним и тем же пользователем. Дополнительно, перевыпуск и отзыв сертификата не требуют изменения конфигурации ClickHouse.
|
||||
|
||||
Для включения аутентификации по SSL сертификату, необходимо указать список `Common Name` для каждого пользователя ClickHouse в файле настройки `config.xml`:
|
||||
Для включения аутентификации по SSL сертификату, необходимо указать список `Common Name` или `subjectAltName` для каждого пользователя ClickHouse в файле настройки `config.xml`:
|
||||
|
||||
**Example**
|
||||
```xml
|
||||
<clickhouse>
|
||||
<!- ... -->
|
||||
<users>
|
||||
<user_name>
|
||||
<certificates>
|
||||
<user_name_1>
|
||||
<ssl_certificates>
|
||||
<common_name>host.domain.com:example_user</common_name>
|
||||
<common_name>host.domain.com:example_user_dev</common_name>
|
||||
<!-- More names -->
|
||||
</certificates>
|
||||
</ssl_certificates>
|
||||
<!-- Other settings -->
|
||||
</user_name>
|
||||
</user_name_1>
|
||||
<user_name_2>
|
||||
<ssl_certificates>
|
||||
<subject_alt_name>DNS:host.domain.com</subject_alt_name>
|
||||
<!-- More names -->
|
||||
</ssl_certificates>
|
||||
<!-- Other settings -->
|
||||
</user_name_2>
|
||||
</users>
|
||||
</clickhouse>
|
||||
```
|
||||
|
@ -13,7 +13,7 @@ sidebar_label: "Пользователь"
|
||||
``` sql
|
||||
CREATE USER [IF NOT EXISTS | OR REPLACE] name1 [ON CLUSTER cluster_name1]
|
||||
[, name2 [ON CLUSTER cluster_name2] ...]
|
||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'}]
|
||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'}]
|
||||
[HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||
[DEFAULT ROLE role [,...]]
|
||||
[DEFAULT DATABASE database | NONE]
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
#include <DataTypes/DataTypeDateTime64.h>
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Common/assert_cast.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
|
||||
@ -47,9 +48,17 @@ Chunk ODBCSource::generate()
|
||||
for (int idx = 0; idx < result.columns(); ++idx)
|
||||
{
|
||||
const auto & sample = description.sample_block.getByPosition(idx);
|
||||
|
||||
if (!result.is_null(idx))
|
||||
insertValue(*columns[idx], removeNullable(sample.type), description.types[idx].first, result, idx);
|
||||
{
|
||||
if (columns[idx]->isNullable())
|
||||
{
|
||||
ColumnNullable & column_nullable = assert_cast<ColumnNullable &>(*columns[idx]);
|
||||
insertValue(column_nullable.getNestedColumn(), removeNullable(sample.type), description.types[idx].first, result, idx);
|
||||
column_nullable.getNullMapData().emplace_back(0);
|
||||
}
|
||||
else
|
||||
insertValue(*columns[idx], removeNullable(sample.type), description.types[idx].first, result, idx);
|
||||
}
|
||||
else
|
||||
insertDefaultValue(*columns[idx], *sample.column);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/SSHWrapper.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@ -238,7 +239,15 @@ bool Authentication::areCredentialsValid(
|
||||
throw Authentication::Require<GSSAcceptorContext>(auth_data.getKerberosRealm());
|
||||
|
||||
case AuthenticationType::SSL_CERTIFICATE:
|
||||
return auth_data.getSSLCertificateCommonNames().contains(ssl_certificate_credentials->getCommonName());
|
||||
for (SSLCertificateSubjects::Type type : {SSLCertificateSubjects::Type::CN, SSLCertificateSubjects::Type::SAN})
|
||||
{
|
||||
for (const auto & subject : auth_data.getSSLCertificateSubjects().at(type))
|
||||
{
|
||||
if (ssl_certificate_credentials->getSSLCertificateSubjects().at(type).contains(subject))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
case AuthenticationType::SSH_KEY:
|
||||
#if USE_SSH
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include "config.h"
|
||||
|
||||
#if USE_SSL
|
||||
@ -107,7 +108,7 @@ bool operator ==(const AuthenticationData & lhs, const AuthenticationData & rhs)
|
||||
{
|
||||
return (lhs.type == rhs.type) && (lhs.password_hash == rhs.password_hash)
|
||||
&& (lhs.ldap_server_name == rhs.ldap_server_name) && (lhs.kerberos_realm == rhs.kerberos_realm)
|
||||
&& (lhs.ssl_certificate_common_names == rhs.ssl_certificate_common_names)
|
||||
&& (lhs.ssl_certificate_subjects == rhs.ssl_certificate_subjects)
|
||||
#if USE_SSH
|
||||
&& (lhs.ssh_keys == rhs.ssh_keys)
|
||||
#endif
|
||||
@ -277,11 +278,16 @@ String AuthenticationData::getSalt() const
|
||||
return salt;
|
||||
}
|
||||
|
||||
void AuthenticationData::setSSLCertificateCommonNames(boost::container::flat_set<String> common_names_)
|
||||
void AuthenticationData::setSSLCertificateSubjects(SSLCertificateSubjects && ssl_certificate_subjects_)
|
||||
{
|
||||
if (common_names_.empty())
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "The 'SSL CERTIFICATE' authentication type requires a non-empty list of common names.");
|
||||
ssl_certificate_common_names = std::move(common_names_);
|
||||
if (ssl_certificate_subjects_.empty())
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "The 'SSL CERTIFICATE' authentication type requires a non-empty list of subjects.");
|
||||
ssl_certificate_subjects = std::move(ssl_certificate_subjects_);
|
||||
}
|
||||
|
||||
void AuthenticationData::addSSLCertificateSubject(SSLCertificateSubjects::Type type_, String && subject_)
|
||||
{
|
||||
ssl_certificate_subjects.insert(type_, std::move(subject_));
|
||||
}
|
||||
|
||||
std::shared_ptr<ASTAuthenticationData> AuthenticationData::toAST() const
|
||||
@ -339,7 +345,14 @@ std::shared_ptr<ASTAuthenticationData> AuthenticationData::toAST() const
|
||||
}
|
||||
case AuthenticationType::SSL_CERTIFICATE:
|
||||
{
|
||||
for (const auto & name : getSSLCertificateCommonNames())
|
||||
using SSLCertificateSubjects::Type::CN;
|
||||
using SSLCertificateSubjects::Type::SAN;
|
||||
|
||||
const auto &subjects = getSSLCertificateSubjects();
|
||||
SSLCertificateSubjects::Type cert_subject_type = !subjects.at(SAN).empty() ? SAN : CN;
|
||||
|
||||
node->ssl_cert_subject_type = toString(cert_subject_type);
|
||||
for (const auto & name : getSSLCertificateSubjects().at(cert_subject_type))
|
||||
node->children.push_back(std::make_shared<ASTLiteral>(name));
|
||||
|
||||
break;
|
||||
@ -513,11 +526,9 @@ AuthenticationData AuthenticationData::fromAST(const ASTAuthenticationData & que
|
||||
}
|
||||
else if (query.type == AuthenticationType::SSL_CERTIFICATE)
|
||||
{
|
||||
boost::container::flat_set<String> common_names;
|
||||
auto ssl_cert_subject_type = parseSSLCertificateSubjectType(*query.ssl_cert_subject_type);
|
||||
for (const auto & arg : args)
|
||||
common_names.insert(checkAndGetLiteralArgument<String>(arg, "common_name"));
|
||||
|
||||
auth_data.setSSLCertificateCommonNames(std::move(common_names));
|
||||
auth_data.addSSLCertificateSubject(ssl_cert_subject_type, checkAndGetLiteralArgument<String>(arg, "ssl_certificate_subject"));
|
||||
}
|
||||
else if (query.type == AuthenticationType::HTTP)
|
||||
{
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
#include <Access/Common/AuthenticationType.h>
|
||||
#include <Access/Common/HTTPAuthenticationScheme.h>
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <Common/SSHWrapper.h>
|
||||
#include <Interpreters/Context_fwd.h>
|
||||
#include <Parsers/Access/ASTAuthenticationData.h>
|
||||
|
||||
#include <vector>
|
||||
#include <base/types.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@ -58,8 +59,9 @@ public:
|
||||
const String & getKerberosRealm() const { return kerberos_realm; }
|
||||
void setKerberosRealm(const String & realm) { kerberos_realm = realm; }
|
||||
|
||||
const boost::container::flat_set<String> & getSSLCertificateCommonNames() const { return ssl_certificate_common_names; }
|
||||
void setSSLCertificateCommonNames(boost::container::flat_set<String> common_names_);
|
||||
const SSLCertificateSubjects & getSSLCertificateSubjects() const { return ssl_certificate_subjects; }
|
||||
void setSSLCertificateSubjects(SSLCertificateSubjects && ssl_certificate_subjects_);
|
||||
void addSSLCertificateSubject(SSLCertificateSubjects::Type type_, String && subject_);
|
||||
|
||||
#if USE_SSH
|
||||
const std::vector<SSHKey> & getSSHKeys() const { return ssh_keys; }
|
||||
@ -96,7 +98,7 @@ private:
|
||||
Digest password_hash;
|
||||
String ldap_server_name;
|
||||
String kerberos_realm;
|
||||
boost::container::flat_set<String> ssl_certificate_common_names;
|
||||
SSLCertificateSubjects ssl_certificate_subjects;
|
||||
String salt;
|
||||
#if USE_SSH
|
||||
std::vector<SSHKey> ssh_keys;
|
||||
|
95
src/Access/Common/SSLCertificateSubjects.cpp
Normal file
95
src/Access/Common/SSLCertificateSubjects.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <Common/Exception.h>
|
||||
|
||||
#if USE_SSL
|
||||
#include <openssl/x509v3.h>
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
#if USE_SSL
|
||||
SSLCertificateSubjects extractSSLCertificateSubjects(const Poco::Net::X509Certificate & certificate)
|
||||
{
|
||||
|
||||
SSLCertificateSubjects subjects;
|
||||
if (!certificate.commonName().empty())
|
||||
{
|
||||
subjects.insert(SSLCertificateSubjects::Type::CN, certificate.commonName());
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wused-but-marked-unused"
|
||||
auto stackof_general_name_deleter = [](void * ptr) { GENERAL_NAMES_free(static_cast<STACK_OF(GENERAL_NAME) *>(ptr)); };
|
||||
std::unique_ptr<void, decltype(stackof_general_name_deleter)> cert_names(
|
||||
X509_get_ext_d2i(const_cast<X509 *>(certificate.certificate()), NID_subject_alt_name, nullptr, nullptr),
|
||||
stackof_general_name_deleter);
|
||||
|
||||
if (STACK_OF(GENERAL_NAME) * names = static_cast<STACK_OF(GENERAL_NAME) *>(cert_names.get()))
|
||||
{
|
||||
for (int i = 0; i < sk_GENERAL_NAME_num(names); ++i)
|
||||
{
|
||||
const GENERAL_NAME * name = sk_GENERAL_NAME_value(names, i);
|
||||
if (name->type == GEN_DNS || name->type == GEN_URI)
|
||||
{
|
||||
const char * data = reinterpret_cast<const char *>(ASN1_STRING_get0_data(name->d.ia5));
|
||||
std::size_t len = ASN1_STRING_length(name->d.ia5);
|
||||
std::string subject = (name->type == GEN_DNS ? "DNS:" : "URI:") + std::string(data, len);
|
||||
subjects.insert(SSLCertificateSubjects::Type::SAN, std::move(subject));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
return subjects;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void SSLCertificateSubjects::insert(const String & subject_type_, String && subject)
|
||||
{
|
||||
insert(parseSSLCertificateSubjectType(subject_type_), std::move(subject));
|
||||
}
|
||||
|
||||
void SSLCertificateSubjects::insert(Type subject_type_, String && subject)
|
||||
{
|
||||
subjects[static_cast<size_t>(subject_type_)].insert(std::move(subject));
|
||||
}
|
||||
|
||||
SSLCertificateSubjects::Type parseSSLCertificateSubjectType(const String & type_)
|
||||
{
|
||||
if (type_ == "CN")
|
||||
return SSLCertificateSubjects::Type::CN;
|
||||
if (type_ == "SAN")
|
||||
return SSLCertificateSubjects::Type::SAN;
|
||||
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown SSL Certificate Subject Type: {}", type_);
|
||||
}
|
||||
|
||||
String toString(SSLCertificateSubjects::Type type_)
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case SSLCertificateSubjects::Type::CN:
|
||||
return "CN";
|
||||
case SSLCertificateSubjects::Type::SAN:
|
||||
return "SAN";
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const SSLCertificateSubjects & lhs, const SSLCertificateSubjects & rhs)
|
||||
{
|
||||
for (SSLCertificateSubjects::Type type : {SSLCertificateSubjects::Type::CN, SSLCertificateSubjects::Type::SAN})
|
||||
{
|
||||
if (lhs.at(type) != rhs.at(type))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
48
src/Access/Common/SSLCertificateSubjects.h
Normal file
48
src/Access/Common/SSLCertificateSubjects.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include <base/types.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
#if USE_SSL
|
||||
# include <Poco/Net/X509Certificate.h>
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class SSLCertificateSubjects
|
||||
{
|
||||
public:
|
||||
using container = boost::container::flat_set<String>;
|
||||
enum class Type
|
||||
{
|
||||
CN,
|
||||
SAN
|
||||
};
|
||||
|
||||
private:
|
||||
std::array<container, size_t(Type::SAN) + 1> subjects;
|
||||
|
||||
public:
|
||||
inline const container & at(Type type_) const { return subjects[static_cast<size_t>(type_)]; }
|
||||
inline bool empty()
|
||||
{
|
||||
for (auto & subject_list : subjects)
|
||||
{
|
||||
if (!subject_list.empty())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void insert(const String & subject_type_, String && subject);
|
||||
void insert(Type type_, String && subject);
|
||||
friend bool operator==(const SSLCertificateSubjects & lhs, const SSLCertificateSubjects & rhs);
|
||||
};
|
||||
|
||||
String toString(SSLCertificateSubjects::Type type_);
|
||||
SSLCertificateSubjects::Type parseSSLCertificateSubjectType(const String & type_);
|
||||
|
||||
#if USE_SSL
|
||||
SSLCertificateSubjects extractSSLCertificateSubjects(const Poco::Net::X509Certificate & certificate);
|
||||
#endif
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#include <Access/Credentials.h>
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <Common/Exception.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
@ -48,18 +48,18 @@ void AlwaysAllowCredentials::setUserName(const String & user_name_)
|
||||
user_name = user_name_;
|
||||
}
|
||||
|
||||
SSLCertificateCredentials::SSLCertificateCredentials(const String & user_name_, const String & common_name_)
|
||||
SSLCertificateCredentials::SSLCertificateCredentials(const String & user_name_, SSLCertificateSubjects && subjects_)
|
||||
: Credentials(user_name_)
|
||||
, common_name(common_name_)
|
||||
, certificate_subjects(subjects_)
|
||||
{
|
||||
is_ready = true;
|
||||
}
|
||||
|
||||
const String & SSLCertificateCredentials::getCommonName() const
|
||||
const SSLCertificateSubjects & SSLCertificateCredentials::getSSLCertificateSubjects() const
|
||||
{
|
||||
if (!isReady())
|
||||
throwNotReady();
|
||||
return common_name;
|
||||
return certificate_subjects;
|
||||
}
|
||||
|
||||
BasicCredentials::BasicCredentials()
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <base/types.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <memory>
|
||||
|
||||
#include "config.h"
|
||||
@ -42,11 +44,11 @@ class SSLCertificateCredentials
|
||||
: public Credentials
|
||||
{
|
||||
public:
|
||||
explicit SSLCertificateCredentials(const String & user_name_, const String & common_name_);
|
||||
const String & getCommonName() const;
|
||||
explicit SSLCertificateCredentials(const String & user_name_, SSLCertificateSubjects && subjects_);
|
||||
const SSLCertificateSubjects & getSSLCertificateSubjects() const;
|
||||
|
||||
private:
|
||||
String common_name;
|
||||
SSLCertificateSubjects certificate_subjects;
|
||||
};
|
||||
|
||||
class BasicCredentials
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <Access/UsersConfigAccessStorage.h>
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <Access/Quota.h>
|
||||
#include <Access/RowPolicy.h>
|
||||
#include <Access/User.h>
|
||||
@ -194,18 +195,23 @@ namespace
|
||||
/// Fill list of allowed certificates.
|
||||
Poco::Util::AbstractConfiguration::Keys keys;
|
||||
config.keys(certificates_config, keys);
|
||||
boost::container::flat_set<String> common_names;
|
||||
for (const String & key : keys)
|
||||
{
|
||||
if (key.starts_with("common_name"))
|
||||
{
|
||||
String value = config.getString(certificates_config + "." + key);
|
||||
common_names.insert(std::move(value));
|
||||
user->auth_data.addSSLCertificateSubject(SSLCertificateSubjects::Type::CN, std::move(value));
|
||||
}
|
||||
else if (key.starts_with("subject_alt_name"))
|
||||
{
|
||||
String value = config.getString(certificates_config + "." + key);
|
||||
if (value.empty())
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Expected ssl_certificates.subject_alt_name to not be empty");
|
||||
user->auth_data.addSSLCertificateSubject(SSLCertificateSubjects::Type::SAN, std::move(value));
|
||||
}
|
||||
else
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown certificate pattern type: {}", key);
|
||||
}
|
||||
user->auth_data.setSSLCertificateCommonNames(std::move(common_names));
|
||||
}
|
||||
else if (has_ssh_keys)
|
||||
{
|
||||
|
@ -1206,11 +1206,8 @@ void ClientBase::receiveResult(ASTPtr parsed_query, Int32 signals_before_stop, b
|
||||
if (local_format_error)
|
||||
std::rethrow_exception(local_format_error);
|
||||
|
||||
if (cancelled && is_interactive)
|
||||
{
|
||||
if (cancelled && is_interactive && !cancelled_printed.exchange(true))
|
||||
output_stream << "Query was cancelled." << std::endl;
|
||||
cancelled_printed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1326,7 +1323,7 @@ void ClientBase::onEndOfStream()
|
||||
|
||||
if (is_interactive)
|
||||
{
|
||||
if (cancelled && !cancelled_printed)
|
||||
if (cancelled && !cancelled_printed.exchange(true))
|
||||
output_stream << "Query was cancelled." << std::endl;
|
||||
else if (!written_first_block)
|
||||
output_stream << "Ok." << std::endl;
|
||||
|
@ -338,8 +338,8 @@ protected:
|
||||
bool allow_repeated_settings = false;
|
||||
bool allow_merge_tree_settings = false;
|
||||
|
||||
bool cancelled = false;
|
||||
bool cancelled_printed = false;
|
||||
std::atomic_bool cancelled = false;
|
||||
std::atomic_bool cancelled_printed = false;
|
||||
|
||||
/// Unpacked descriptors and streams for the ease of use.
|
||||
int in_fd = STDIN_FILENO;
|
||||
|
@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <type_traits>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
@ -200,22 +198,18 @@ public:
|
||||
*/
|
||||
bool finish()
|
||||
{
|
||||
bool was_finished_before = false;
|
||||
|
||||
{
|
||||
std::lock_guard lock(queue_mutex);
|
||||
|
||||
if (is_finished)
|
||||
return true;
|
||||
|
||||
was_finished_before = is_finished;
|
||||
is_finished = true;
|
||||
}
|
||||
|
||||
pop_condition.notify_all();
|
||||
push_condition.notify_all();
|
||||
|
||||
return was_finished_before;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns if queue is finished
|
||||
|
@ -447,14 +447,18 @@ The server successfully detected this situation and will download merged part fr
|
||||
M(QueryMemoryLimitExceeded, "Number of times when memory limit exceeded for query.") \
|
||||
\
|
||||
M(AzureGetObject, "Number of Azure API GetObject calls.") \
|
||||
M(AzureUploadPart, "Number of Azure blob storage API UploadPart calls") \
|
||||
M(AzureUpload, "Number of Azure blob storage API Upload calls") \
|
||||
M(AzureStageBlock, "Number of Azure blob storage API StageBlock calls") \
|
||||
M(AzureCommitBlockList, "Number of Azure blob storage API CommitBlockList calls") \
|
||||
M(AzureCopyObject, "Number of Azure blob storage API CopyObject calls") \
|
||||
M(AzureDeleteObjects, "Number of Azure blob storage API DeleteObject(s) calls.") \
|
||||
M(AzureListObjects, "Number of Azure blob storage API ListObjects calls.") \
|
||||
M(AzureGetProperties, "Number of Azure blob storage API GetProperties calls.") \
|
||||
\
|
||||
M(DiskAzureGetObject, "Number of Disk Azure API GetObject calls.") \
|
||||
M(DiskAzureUploadPart, "Number of Disk Azure blob storage API UploadPart calls") \
|
||||
M(DiskAzureUpload, "Number of Disk Azure blob storage API Upload calls") \
|
||||
M(DiskAzureStageBlock, "Number of Disk Azure blob storage API StageBlock calls") \
|
||||
M(DiskAzureCommitBlockList, "Number of Disk Azure blob storage API CommitBlockList calls") \
|
||||
M(DiskAzureCopyObject, "Number of Disk Azure blob storage API CopyObject calls") \
|
||||
M(DiskAzureListObjects, "Number of Disk Azure blob storage API ListObjects calls.") \
|
||||
M(DiskAzureDeleteObjects, "Number of Azure blob storage API DeleteObject(s) calls.") \
|
||||
@ -611,6 +615,13 @@ The server successfully detected this situation and will download merged part fr
|
||||
M(KeeperPacketsReceived, "Packets received by keeper server") \
|
||||
M(KeeperRequestTotal, "Total requests number on keeper server") \
|
||||
M(KeeperLatency, "Keeper latency") \
|
||||
M(KeeperTotalElapsedMicroseconds, "Keeper total latency for a single request") \
|
||||
M(KeeperProcessElapsedMicroseconds, "Keeper commit latency for a single request") \
|
||||
M(KeeperPreprocessElapsedMicroseconds, "Keeper preprocessing latency for a single reuquest") \
|
||||
M(KeeperStorageLockWaitMicroseconds, "Time spent waiting for acquiring Keeper storage lock") \
|
||||
M(KeeperCommitWaitElapsedMicroseconds, "Time spent waiting for certain log to be committed") \
|
||||
M(KeeperBatchMaxCount, "Number of times the size of batch was limited by the amount") \
|
||||
M(KeeperBatchMaxTotalSize, "Number of times the size of batch was limited by the total bytes size") \
|
||||
M(KeeperCommits, "Number of successful commits") \
|
||||
M(KeeperCommitsFailed, "Number of failed commits") \
|
||||
M(KeeperSnapshotCreations, "Number of snapshots creations")\
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <fmt/format.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <array>
|
||||
|
||||
|
||||
namespace Coordination
|
||||
@ -29,7 +28,7 @@ void ZooKeeperResponse::write(WriteBuffer & out) const
|
||||
Coordination::write(buf.str(), out);
|
||||
}
|
||||
|
||||
std::string ZooKeeperRequest::toString() const
|
||||
std::string ZooKeeperRequest::toString(bool short_format) const
|
||||
{
|
||||
return fmt::format(
|
||||
"XID = {}\n"
|
||||
@ -37,7 +36,7 @@ std::string ZooKeeperRequest::toString() const
|
||||
"Additional info:\n{}",
|
||||
xid,
|
||||
getOpNum(),
|
||||
toStringImpl());
|
||||
toStringImpl(short_format));
|
||||
}
|
||||
|
||||
void ZooKeeperRequest::write(WriteBuffer & out) const
|
||||
@ -60,7 +59,7 @@ void ZooKeeperSyncRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(path, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperSyncRequest::toStringImpl() const
|
||||
std::string ZooKeeperSyncRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}", path);
|
||||
}
|
||||
@ -91,7 +90,7 @@ void ZooKeeperReconfigRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(version, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperReconfigRequest::toStringImpl() const
|
||||
std::string ZooKeeperReconfigRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format(
|
||||
"joining = {}\nleaving = {}\nnew_members = {}\nversion = {}",
|
||||
@ -145,7 +144,7 @@ void ZooKeeperAuthRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(data, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperAuthRequest::toStringImpl() const
|
||||
std::string ZooKeeperAuthRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format(
|
||||
"type = {}\n"
|
||||
@ -191,7 +190,7 @@ void ZooKeeperCreateRequest::readImpl(ReadBuffer & in)
|
||||
is_sequential = true;
|
||||
}
|
||||
|
||||
std::string ZooKeeperCreateRequest::toStringImpl() const
|
||||
std::string ZooKeeperCreateRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format(
|
||||
"path = {}\n"
|
||||
@ -218,7 +217,7 @@ void ZooKeeperRemoveRequest::writeImpl(WriteBuffer & out) const
|
||||
Coordination::write(version, out);
|
||||
}
|
||||
|
||||
std::string ZooKeeperRemoveRequest::toStringImpl() const
|
||||
std::string ZooKeeperRemoveRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format(
|
||||
"path = {}\n"
|
||||
@ -245,7 +244,7 @@ void ZooKeeperExistsRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(has_watch, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperExistsRequest::toStringImpl() const
|
||||
std::string ZooKeeperExistsRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}", path);
|
||||
}
|
||||
@ -272,7 +271,7 @@ void ZooKeeperGetRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(has_watch, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperGetRequest::toStringImpl() const
|
||||
std::string ZooKeeperGetRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}", path);
|
||||
}
|
||||
@ -303,7 +302,7 @@ void ZooKeeperSetRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(version, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperSetRequest::toStringImpl() const
|
||||
std::string ZooKeeperSetRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format(
|
||||
"path = {}\n"
|
||||
@ -334,7 +333,7 @@ void ZooKeeperListRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(has_watch, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperListRequest::toStringImpl() const
|
||||
std::string ZooKeeperListRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}", path);
|
||||
}
|
||||
@ -356,7 +355,7 @@ void ZooKeeperFilteredListRequest::readImpl(ReadBuffer & in)
|
||||
list_request_type = static_cast<ListRequestType>(read_request_type);
|
||||
}
|
||||
|
||||
std::string ZooKeeperFilteredListRequest::toStringImpl() const
|
||||
std::string ZooKeeperFilteredListRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format(
|
||||
"path = {}\n"
|
||||
@ -401,7 +400,7 @@ void ZooKeeperSetACLRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(version, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperSetACLRequest::toStringImpl() const
|
||||
std::string ZooKeeperSetACLRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}\nversion = {}", path, version);
|
||||
}
|
||||
@ -426,7 +425,7 @@ void ZooKeeperGetACLRequest::writeImpl(WriteBuffer & out) const
|
||||
Coordination::write(path, out);
|
||||
}
|
||||
|
||||
std::string ZooKeeperGetACLRequest::toStringImpl() const
|
||||
std::string ZooKeeperGetACLRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}", path);
|
||||
}
|
||||
@ -455,7 +454,7 @@ void ZooKeeperCheckRequest::readImpl(ReadBuffer & in)
|
||||
Coordination::read(version, in);
|
||||
}
|
||||
|
||||
std::string ZooKeeperCheckRequest::toStringImpl() const
|
||||
std::string ZooKeeperCheckRequest::toStringImpl(bool /*short_format*/) const
|
||||
{
|
||||
return fmt::format("path = {}\nversion = {}", path, version);
|
||||
}
|
||||
@ -600,8 +599,11 @@ void ZooKeeperMultiRequest::readImpl(ReadBuffer & in)
|
||||
}
|
||||
}
|
||||
|
||||
std::string ZooKeeperMultiRequest::toStringImpl() const
|
||||
std::string ZooKeeperMultiRequest::toStringImpl(bool short_format) const
|
||||
{
|
||||
if (short_format)
|
||||
return fmt::format("Subrequests size = {}", requests.size());
|
||||
|
||||
auto out = fmt::memory_buffer();
|
||||
for (const auto & request : requests)
|
||||
{
|
||||
|
@ -63,12 +63,12 @@ struct ZooKeeperRequest : virtual Request
|
||||
|
||||
/// Writes length, xid, op_num, then the rest.
|
||||
void write(WriteBuffer & out) const;
|
||||
std::string toString() const;
|
||||
std::string toString(bool short_format = false) const;
|
||||
|
||||
virtual void writeImpl(WriteBuffer &) const = 0;
|
||||
virtual void readImpl(ReadBuffer &) = 0;
|
||||
|
||||
virtual std::string toStringImpl() const { return ""; }
|
||||
virtual std::string toStringImpl(bool /*short_format*/) const { return ""; }
|
||||
|
||||
static std::shared_ptr<ZooKeeperRequest> read(ReadBuffer & in);
|
||||
|
||||
@ -98,7 +98,7 @@ struct ZooKeeperSyncRequest final : ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Sync; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
|
||||
@ -123,7 +123,7 @@ struct ZooKeeperReconfigRequest final : ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Reconfig; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
|
||||
@ -176,7 +176,7 @@ struct ZooKeeperAuthRequest final : ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Auth; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
@ -229,7 +229,7 @@ struct ZooKeeperCreateRequest final : public CreateRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return not_exists ? OpNum::CreateIfNotExists : OpNum::Create; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
@ -266,7 +266,7 @@ struct ZooKeeperRemoveRequest final : RemoveRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Remove; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
@ -293,7 +293,7 @@ struct ZooKeeperExistsRequest final : ExistsRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Exists; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return true; }
|
||||
@ -320,7 +320,7 @@ struct ZooKeeperGetRequest final : GetRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Get; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return true; }
|
||||
@ -347,7 +347,7 @@ struct ZooKeeperSetRequest final : SetRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::Set; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
|
||||
@ -375,7 +375,7 @@ struct ZooKeeperListRequest : ListRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::List; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return true; }
|
||||
|
||||
@ -395,7 +395,7 @@ struct ZooKeeperFilteredListRequest final : ZooKeeperListRequest
|
||||
OpNum getOpNum() const override { return OpNum::FilteredList; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
size_t bytesSize() const override { return ZooKeeperListRequest::bytesSize() + sizeof(list_request_type); }
|
||||
};
|
||||
@ -428,7 +428,7 @@ struct ZooKeeperCheckRequest : CheckRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return not_exists ? OpNum::CheckNotExists : OpNum::Check; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return true; }
|
||||
@ -469,7 +469,7 @@ struct ZooKeeperSetACLRequest final : SetACLRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::SetACL; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return false; }
|
||||
|
||||
@ -490,7 +490,7 @@ struct ZooKeeperGetACLRequest final : GetACLRequest, ZooKeeperRequest
|
||||
OpNum getOpNum() const override { return OpNum::GetACL; }
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override { return true; }
|
||||
|
||||
@ -516,7 +516,7 @@ struct ZooKeeperMultiRequest final : MultiRequest, ZooKeeperRequest
|
||||
|
||||
void writeImpl(WriteBuffer & out) const override;
|
||||
void readImpl(ReadBuffer & in) override;
|
||||
std::string toStringImpl() const override;
|
||||
std::string toStringImpl(bool short_format) const override;
|
||||
|
||||
ZooKeeperResponsePtr makeResponse() const override;
|
||||
bool isReadRequest() const override;
|
||||
|
@ -169,6 +169,23 @@ void KeeperConfigurationAndSettings::dump(WriteBufferFromOwnString & buf) const
|
||||
|
||||
writeText("async_replication=", buf);
|
||||
write_bool(coordination_settings->async_replication);
|
||||
|
||||
writeText("latest_logs_cache_size_threshold=", buf);
|
||||
write_int(coordination_settings->latest_logs_cache_size_threshold);
|
||||
writeText("commit_logs_cache_size_threshold=", buf);
|
||||
write_int(coordination_settings->commit_logs_cache_size_threshold);
|
||||
|
||||
writeText("disk_move_retries_wait_ms=", buf);
|
||||
write_int(coordination_settings->disk_move_retries_wait_ms);
|
||||
writeText("disk_move_retries_during_init=", buf);
|
||||
write_int(coordination_settings->disk_move_retries_during_init);
|
||||
|
||||
writeText("log_slow_total_threshold_ms=", buf);
|
||||
write_int(coordination_settings->log_slow_total_threshold_ms);
|
||||
writeText("log_slow_cpu_threshold_ms=", buf);
|
||||
write_int(coordination_settings->log_slow_cpu_threshold_ms);
|
||||
writeText("log_slow_connection_operation_threshold_ms=", buf);
|
||||
write_int(coordination_settings->log_slow_connection_operation_threshold_ms);
|
||||
}
|
||||
|
||||
KeeperConfigurationAndSettingsPtr
|
||||
|
@ -58,7 +58,10 @@ struct Settings;
|
||||
M(UInt64, latest_logs_cache_size_threshold, 1 * 1024 * 1024 * 1024, "Maximum total size of in-memory cache of latest log entries.", 0) \
|
||||
M(UInt64, commit_logs_cache_size_threshold, 500 * 1024 * 1024, "Maximum total size of in-memory cache of log entries needed next for commit.", 0) \
|
||||
M(UInt64, disk_move_retries_wait_ms, 1000, "How long to wait between retries after a failure which happened while a file was being moved between disks.", 0) \
|
||||
M(UInt64, disk_move_retries_during_init, 100, "The amount of retries after a failure which happened while a file was being moved between disks during initialization.", 0)
|
||||
M(UInt64, disk_move_retries_during_init, 100, "The amount of retries after a failure which happened while a file was being moved between disks during initialization.", 0) \
|
||||
M(UInt64, log_slow_total_threshold_ms, 5000, "Requests for which the total latency is larger than this settings will be logged", 0) \
|
||||
M(UInt64, log_slow_cpu_threshold_ms, 100, "Requests for which the CPU (preprocessing and processing) latency is larger than this settings will be logged", 0) \
|
||||
M(UInt64, log_slow_connection_operation_threshold_ms, 1000, "Log message if a certain operation took too long inside a single connection", 0)
|
||||
|
||||
DECLARE_SETTINGS_TRAITS(CoordinationSettingsTraits, LIST_OF_COORDINATION_SETTINGS)
|
||||
|
||||
|
@ -150,12 +150,18 @@
|
||||
M(S3PutObject) \
|
||||
M(S3GetObject) \
|
||||
\
|
||||
M(AzureUploadPart) \
|
||||
M(DiskAzureUploadPart) \
|
||||
M(AzureUpload) \
|
||||
M(DiskAzureUpload) \
|
||||
M(AzureStageBlock) \
|
||||
M(DiskAzureStageBlock) \
|
||||
M(AzureCommitBlockList) \
|
||||
M(DiskAzureCommitBlockList) \
|
||||
M(AzureCopyObject) \
|
||||
M(DiskAzureCopyObject) \
|
||||
M(AzureDeleteObjects) \
|
||||
M(DiskAzureDeleteObjects) \
|
||||
M(AzureListObjects) \
|
||||
M(DiskAzureListObjects) \
|
||||
\
|
||||
M(DiskS3DeleteObjects) \
|
||||
M(DiskS3CopyObject) \
|
||||
@ -238,6 +244,13 @@
|
||||
M(KeeperPacketsReceived) \
|
||||
M(KeeperRequestTotal) \
|
||||
M(KeeperLatency) \
|
||||
M(KeeperTotalElapsedMicroseconds) \
|
||||
M(KeeperProcessElapsedMicroseconds) \
|
||||
M(KeeperPreprocessElapsedMicroseconds) \
|
||||
M(KeeperStorageLockWaitMicroseconds) \
|
||||
M(KeeperCommitWaitElapsedMicroseconds) \
|
||||
M(KeeperBatchMaxCount) \
|
||||
M(KeeperBatchMaxTotalSize) \
|
||||
M(KeeperCommits) \
|
||||
M(KeeperCommitsFailed) \
|
||||
M(KeeperSnapshotCreations) \
|
||||
|
@ -31,6 +31,13 @@ namespace CurrentMetrics
|
||||
extern const Metric KeeperOutstandingRequets;
|
||||
}
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event KeeperCommitWaitElapsedMicroseconds;
|
||||
extern const Event KeeperBatchMaxCount;
|
||||
extern const Event KeeperBatchMaxTotalSize;
|
||||
}
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace DB
|
||||
@ -119,6 +126,7 @@ void KeeperDispatcher::requestThread()
|
||||
auto coordination_settings = configuration_and_settings->coordination_settings;
|
||||
uint64_t max_wait = coordination_settings->operation_timeout_ms.totalMilliseconds();
|
||||
uint64_t max_batch_bytes_size = coordination_settings->max_requests_batch_bytes_size;
|
||||
size_t max_batch_size = coordination_settings->max_requests_batch_size;
|
||||
|
||||
/// The code below do a very simple thing: batch all write (quorum) requests into vector until
|
||||
/// previous write batch is not finished or max_batch size achieved. The main complexity goes from
|
||||
@ -188,7 +196,6 @@ void KeeperDispatcher::requestThread()
|
||||
return false;
|
||||
};
|
||||
|
||||
size_t max_batch_size = coordination_settings->max_requests_batch_size;
|
||||
while (!shutdown_called && current_batch.size() < max_batch_size && !has_reconfig_request
|
||||
&& current_batch_bytes_size < max_batch_bytes_size && try_get_request())
|
||||
;
|
||||
@ -225,6 +232,12 @@ void KeeperDispatcher::requestThread()
|
||||
/// Process collected write requests batch
|
||||
if (!current_batch.empty())
|
||||
{
|
||||
if (current_batch.size() == max_batch_size)
|
||||
ProfileEvents::increment(ProfileEvents::KeeperBatchMaxCount, 1);
|
||||
|
||||
if (current_batch_bytes_size == max_batch_bytes_size)
|
||||
ProfileEvents::increment(ProfileEvents::KeeperBatchMaxTotalSize, 1);
|
||||
|
||||
LOG_TRACE(log, "Processing requests batch, size: {}, bytes: {}", current_batch.size(), current_batch_bytes_size);
|
||||
|
||||
auto result = server->putRequestBatch(current_batch);
|
||||
@ -243,6 +256,8 @@ void KeeperDispatcher::requestThread()
|
||||
/// If we will execute read or reconfig next, we have to process result now
|
||||
if (execute_requests_after_write)
|
||||
{
|
||||
Stopwatch watch;
|
||||
SCOPE_EXIT(ProfileEvents::increment(ProfileEvents::KeeperCommitWaitElapsedMicroseconds, watch.elapsedMicroseconds()));
|
||||
if (prev_result)
|
||||
result_buf = forceWaitAndProcessResult(
|
||||
prev_result, prev_batch, /*clear_requests_on_success=*/!execute_requests_after_write);
|
||||
@ -319,19 +334,13 @@ void KeeperDispatcher::snapshotThread()
|
||||
{
|
||||
setThreadName("KeeperSnpT");
|
||||
const auto & shutdown_called = keeper_context->isShutdownCalled();
|
||||
while (!shutdown_called)
|
||||
CreateSnapshotTask task;
|
||||
while (snapshots_queue.pop(task))
|
||||
{
|
||||
CreateSnapshotTask task;
|
||||
if (!snapshots_queue.pop(task))
|
||||
break;
|
||||
|
||||
try
|
||||
{
|
||||
auto snapshot_file_info = task.create_snapshot(std::move(task.snapshot), /*execute_only_cleanup=*/shutdown_called);
|
||||
|
||||
if (shutdown_called)
|
||||
break;
|
||||
|
||||
if (!snapshot_file_info)
|
||||
continue;
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
#include <atomic>
|
||||
#include <cerrno>
|
||||
#include <chrono>
|
||||
#include <Coordination/KeeperDispatcher.h>
|
||||
#include <Coordination/KeeperReconfiguration.h>
|
||||
#include <Coordination/KeeperSnapshotManager.h>
|
||||
#include <Coordination/KeeperStateMachine.h>
|
||||
#include <Coordination/KeeperDispatcher.h>
|
||||
#include <Coordination/KeeperStorage.h>
|
||||
#include <Coordination/KeeperReconfiguration.h>
|
||||
#include <Coordination/ReadBufferFromNuraftBuffer.h>
|
||||
#include <Coordination/WriteBufferFromNuraftBuffer.h>
|
||||
#include <Disks/DiskLocal.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <base/defines.h>
|
||||
#include <base/errnoToString.h>
|
||||
@ -17,7 +19,6 @@
|
||||
#include <Common/ZooKeeper/ZooKeeperCommon.h>
|
||||
#include <Common/ZooKeeper/ZooKeeperIO.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <Disks/DiskLocal.h>
|
||||
|
||||
|
||||
namespace ProfileEvents
|
||||
@ -31,6 +32,7 @@ namespace ProfileEvents
|
||||
extern const Event KeeperSnapshotApplysFailed;
|
||||
extern const Event KeeperReadSnapshot;
|
||||
extern const Event KeeperSaveSnapshot;
|
||||
extern const Event KeeperStorageLockWaitMicroseconds;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
@ -151,6 +153,20 @@ void assertDigest(
|
||||
}
|
||||
}
|
||||
|
||||
struct TSA_SCOPED_LOCKABLE LockGuardWithStats final
|
||||
{
|
||||
std::unique_lock<std::mutex> lock;
|
||||
explicit LockGuardWithStats(std::mutex & mutex) TSA_ACQUIRE(mutex)
|
||||
{
|
||||
Stopwatch watch;
|
||||
std::unique_lock l(mutex);
|
||||
ProfileEvents::increment(ProfileEvents::KeeperStorageLockWaitMicroseconds, watch.elapsedMicroseconds());
|
||||
lock = std::move(l);
|
||||
}
|
||||
|
||||
~LockGuardWithStats() TSA_RELEASE() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
nuraft::ptr<nuraft::buffer> KeeperStateMachine::pre_commit(uint64_t log_idx, nuraft::buffer & data)
|
||||
@ -272,7 +288,7 @@ bool KeeperStateMachine::preprocess(const KeeperStorage::RequestForSession & req
|
||||
if (op_num == Coordination::OpNum::SessionID || op_num == Coordination::OpNum::Reconfig)
|
||||
return true;
|
||||
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
|
||||
if (storage->isFinalized())
|
||||
return false;
|
||||
@ -302,7 +318,7 @@ bool KeeperStateMachine::preprocess(const KeeperStorage::RequestForSession & req
|
||||
|
||||
void KeeperStateMachine::reconfigure(const KeeperStorage::RequestForSession& request_for_session)
|
||||
{
|
||||
std::lock_guard _(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
KeeperStorage::ResponseForSession response = processReconfiguration(request_for_session);
|
||||
if (!responses_queue.push(response))
|
||||
{
|
||||
@ -391,7 +407,7 @@ nuraft::ptr<nuraft::buffer> KeeperStateMachine::commit(const uint64_t log_idx, n
|
||||
if (!keeper_context->localLogsPreprocessed() && !preprocess(*request_for_session))
|
||||
return nullptr;
|
||||
|
||||
auto try_push = [this](const KeeperStorage::ResponseForSession& response)
|
||||
auto try_push = [&](const KeeperStorage::ResponseForSession& response)
|
||||
{
|
||||
if (!responses_queue.push(response))
|
||||
{
|
||||
@ -400,6 +416,17 @@ nuraft::ptr<nuraft::buffer> KeeperStateMachine::commit(const uint64_t log_idx, n
|
||||
"Failed to push response with session id {} to the queue, probably because of shutdown",
|
||||
response.session_id);
|
||||
}
|
||||
|
||||
using namespace std::chrono;
|
||||
uint64_t elapsed = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - request_for_session->time;
|
||||
if (elapsed > keeper_context->getCoordinationSettings()->log_slow_total_threshold_ms)
|
||||
{
|
||||
LOG_INFO(
|
||||
log,
|
||||
"Total time to process a request took too long ({}ms).\nRequest info: {}",
|
||||
elapsed,
|
||||
request_for_session->request->toString(/*short_format=*/true));
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
@ -417,7 +444,7 @@ nuraft::ptr<nuraft::buffer> KeeperStateMachine::commit(const uint64_t log_idx, n
|
||||
response_for_session.session_id = -1;
|
||||
response_for_session.response = response;
|
||||
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
session_id = storage->getSessionID(session_id_request.session_timeout_ms);
|
||||
LOG_DEBUG(log, "Session ID response {} with timeout {}", session_id, session_id_request.session_timeout_ms);
|
||||
response->session_id = session_id;
|
||||
@ -426,12 +453,13 @@ nuraft::ptr<nuraft::buffer> KeeperStateMachine::commit(const uint64_t log_idx, n
|
||||
else
|
||||
{
|
||||
if (op_num == Coordination::OpNum::Close)
|
||||
|
||||
{
|
||||
std::lock_guard lock(request_cache_mutex);
|
||||
parsed_request_cache.erase(request_for_session->session_id);
|
||||
}
|
||||
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
KeeperStorage::ResponsesForSessions responses_for_sessions
|
||||
= storage->processRequest(request_for_session->request, request_for_session->session_id, request_for_session->zxid);
|
||||
for (auto & response_for_session : responses_for_sessions)
|
||||
@ -482,7 +510,7 @@ bool KeeperStateMachine::apply_snapshot(nuraft::snapshot & s)
|
||||
}
|
||||
|
||||
{ /// deserialize and apply snapshot to storage
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
|
||||
SnapshotDeserializationResult snapshot_deserialization_result;
|
||||
if (latest_snapshot_ptr)
|
||||
@ -534,7 +562,7 @@ void KeeperStateMachine::rollbackRequest(const KeeperStorage::RequestForSession
|
||||
if (request_for_session.request->getOpNum() == Coordination::OpNum::SessionID)
|
||||
return;
|
||||
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
storage->rollbackRequest(request_for_session.zxid, allow_missing);
|
||||
}
|
||||
|
||||
@ -561,7 +589,7 @@ void KeeperStateMachine::create_snapshot(nuraft::snapshot & s, nuraft::async_res
|
||||
auto snapshot_meta_copy = nuraft::snapshot::deserialize(*snp_buf);
|
||||
CreateSnapshotTask snapshot_task;
|
||||
{ /// lock storage for a short period time to turn on "snapshot mode". After that we can read consistent storage state without locking.
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
snapshot_task.snapshot = std::make_shared<KeeperStorageSnapshot>(storage.get(), snapshot_meta_copy, getClusterConfig());
|
||||
}
|
||||
|
||||
@ -569,7 +597,7 @@ void KeeperStateMachine::create_snapshot(nuraft::snapshot & s, nuraft::async_res
|
||||
snapshot_task.create_snapshot = [this, when_done](KeeperStorageSnapshotPtr && snapshot, bool execute_only_cleanup)
|
||||
{
|
||||
nuraft::ptr<std::exception> exception(nullptr);
|
||||
bool ret = true;
|
||||
bool ret = false;
|
||||
if (!execute_only_cleanup)
|
||||
{
|
||||
try
|
||||
@ -599,7 +627,8 @@ void KeeperStateMachine::create_snapshot(nuraft::snapshot & s, nuraft::async_res
|
||||
else
|
||||
{
|
||||
auto snapshot_buf = snapshot_manager.serializeSnapshotToBuffer(*snapshot);
|
||||
auto snapshot_info = snapshot_manager.serializeSnapshotBufferToDisk(*snapshot_buf, snapshot->snapshot_meta->get_last_log_idx());
|
||||
auto snapshot_info = snapshot_manager.serializeSnapshotBufferToDisk(
|
||||
*snapshot_buf, snapshot->snapshot_meta->get_last_log_idx());
|
||||
latest_snapshot_info = std::move(snapshot_info);
|
||||
latest_snapshot_buf = std::move(snapshot_buf);
|
||||
}
|
||||
@ -612,18 +641,19 @@ void KeeperStateMachine::create_snapshot(nuraft::snapshot & s, nuraft::async_res
|
||||
latest_snapshot_info->path);
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ProfileEvents::increment(ProfileEvents::KeeperSnapshotCreationsFailed);
|
||||
LOG_TRACE(log, "Exception happened during snapshot");
|
||||
tryLogCurrentException(log);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
{
|
||||
/// Destroy snapshot with lock
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
LOG_TRACE(log, "Clearing garbage after snapshot");
|
||||
/// Turn off "snapshot mode" and clear outdate part of storage state
|
||||
storage->clearGarbageAfterSnapshot();
|
||||
@ -764,7 +794,7 @@ int KeeperStateMachine::read_logical_snp_obj(
|
||||
void KeeperStateMachine::processReadRequest(const KeeperStorage::RequestForSession & request_for_session)
|
||||
{
|
||||
/// Pure local request, just process it with storage
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
auto responses = storage->processRequest(
|
||||
request_for_session.request, request_for_session.session_id, std::nullopt, true /*check_acl*/, true /*is_local*/);
|
||||
for (const auto & response : responses)
|
||||
@ -774,97 +804,97 @@ void KeeperStateMachine::processReadRequest(const KeeperStorage::RequestForSessi
|
||||
|
||||
void KeeperStateMachine::shutdownStorage()
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
storage->finalize();
|
||||
}
|
||||
|
||||
std::vector<int64_t> KeeperStateMachine::getDeadSessions()
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getDeadSessions();
|
||||
}
|
||||
|
||||
int64_t KeeperStateMachine::getNextZxid() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getNextZXID();
|
||||
}
|
||||
|
||||
KeeperStorage::Digest KeeperStateMachine::getNodesDigest() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getNodesDigest(false);
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getLastProcessedZxid() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getZXID();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getNodesCount() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getNodesCount();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getTotalWatchesCount() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getTotalWatchesCount();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getWatchedPathsCount() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getWatchedPathsCount();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getSessionsWithWatchesCount() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getSessionsWithWatchesCount();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getTotalEphemeralNodesCount() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getTotalEphemeralNodesCount();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getSessionWithEphemeralNodesCount() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getSessionWithEphemeralNodesCount();
|
||||
}
|
||||
|
||||
void KeeperStateMachine::dumpWatches(WriteBufferFromOwnString & buf) const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
storage->dumpWatches(buf);
|
||||
}
|
||||
|
||||
void KeeperStateMachine::dumpWatchesByPath(WriteBufferFromOwnString & buf) const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
storage->dumpWatchesByPath(buf);
|
||||
}
|
||||
|
||||
void KeeperStateMachine::dumpSessionsAndEphemerals(WriteBufferFromOwnString & buf) const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
storage->dumpSessionsAndEphemerals(buf);
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getApproximateDataSize() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getApproximateDataSize();
|
||||
}
|
||||
|
||||
uint64_t KeeperStateMachine::getKeyArenaSize() const
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
return storage->getArenaDataSize();
|
||||
}
|
||||
|
||||
@ -905,7 +935,7 @@ ClusterConfigPtr KeeperStateMachine::getClusterConfig() const
|
||||
|
||||
void KeeperStateMachine::recalculateStorageStats()
|
||||
{
|
||||
std::lock_guard lock(storage_and_responses_lock);
|
||||
LockGuardWithStats lock(storage_and_responses_lock);
|
||||
LOG_INFO(log, "Recalculating storage stats");
|
||||
storage->recalculateStats();
|
||||
LOG_INFO(log, "Done recalculating storage stats");
|
||||
|
@ -182,8 +182,7 @@ private:
|
||||
|
||||
KeeperSnapshotManagerS3 * snapshot_manager_s3;
|
||||
|
||||
KeeperStorage::ResponseForSession processReconfiguration(
|
||||
const KeeperStorage::RequestForSession& request_for_session)
|
||||
KeeperStorage::ResponseForSession processReconfiguration(const KeeperStorage::RequestForSession & request_for_session)
|
||||
TSA_REQUIRES(storage_and_responses_lock);
|
||||
};
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ namespace ProfileEvents
|
||||
extern const Event KeeperGetRequest;
|
||||
extern const Event KeeperListRequest;
|
||||
extern const Event KeeperExistsRequest;
|
||||
extern const Event KeeperPreprocessElapsedMicroseconds;
|
||||
extern const Event KeeperProcessElapsedMicroseconds;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
@ -2309,6 +2311,20 @@ void KeeperStorage::preprocessRequest(
|
||||
std::optional<Digest> digest,
|
||||
int64_t log_idx)
|
||||
{
|
||||
Stopwatch watch;
|
||||
SCOPE_EXIT({
|
||||
auto elapsed = watch.elapsedMicroseconds();
|
||||
if (auto elapsed_ms = elapsed / 1000; elapsed_ms > keeper_context->getCoordinationSettings()->log_slow_cpu_threshold_ms)
|
||||
{
|
||||
LOG_INFO(
|
||||
getLogger("KeeperStorage"),
|
||||
"Preprocessing a request took too long ({}ms).\nRequest info: {}",
|
||||
elapsed_ms,
|
||||
zk_request->toString(/*short_format=*/true));
|
||||
}
|
||||
ProfileEvents::increment(ProfileEvents::KeeperPreprocessElapsedMicroseconds, elapsed);
|
||||
});
|
||||
|
||||
if (!initialized)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "KeeperStorage system nodes are not initialized");
|
||||
|
||||
@ -2409,6 +2425,20 @@ KeeperStorage::ResponsesForSessions KeeperStorage::processRequest(
|
||||
bool check_acl,
|
||||
bool is_local)
|
||||
{
|
||||
Stopwatch watch;
|
||||
SCOPE_EXIT({
|
||||
auto elapsed = watch.elapsedMicroseconds();
|
||||
if (auto elapsed_ms = elapsed / 1000; elapsed_ms > keeper_context->getCoordinationSettings()->log_slow_cpu_threshold_ms)
|
||||
{
|
||||
LOG_INFO(
|
||||
getLogger("KeeperStorage"),
|
||||
"Processing a request took too long ({}ms).\nRequest info: {}",
|
||||
elapsed_ms,
|
||||
zk_request->toString(/*short_format=*/true));
|
||||
}
|
||||
ProfileEvents::increment(ProfileEvents::KeeperProcessElapsedMicroseconds, elapsed);
|
||||
});
|
||||
|
||||
if (!initialized)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "KeeperStorage system nodes are not initialized");
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Common/ArenaUtils.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -58,6 +58,7 @@ String ClickHouseVersion::toString() const
|
||||
static std::initializer_list<std::pair<ClickHouseVersion, SettingsChangesHistory::SettingsChanges>> settings_changes_history_initializer =
|
||||
{
|
||||
{"24.7", {{"output_format_parquet_write_page_index", false, true, "Add a possibility to write page index into parquet files."},
|
||||
{"input_format_json_ignore_key_case", false, false, "Ignore json key case while read json field from string."},
|
||||
{"optimize_trivial_insert_select", true, false, "The optimization does not make sense in many cases."},
|
||||
}},
|
||||
{"24.6", {{"materialize_skip_indexes_on_insert", true, true, "Added new setting to allow to disable materialization of skip indexes on insert"},
|
||||
@ -89,7 +90,6 @@ static std::initializer_list<std::pair<ClickHouseVersion, SettingsChangesHistory
|
||||
{"output_format_csv_serialize_tuple_into_separate_columns", true, true, "A new way of how interpret tuples in CSV format was added."},
|
||||
{"input_format_csv_deserialize_separate_columns_into_tuple", true, true, "A new way of how interpret tuples in CSV format was added."},
|
||||
{"input_format_csv_try_infer_strings_from_quoted_tuples", true, true, "A new way of how interpret tuples in CSV format was added."},
|
||||
{"input_format_json_ignore_key_case", false, false, "Ignore json key case while read json field from string."},
|
||||
}},
|
||||
{"24.5", {{"allow_deprecated_error_prone_window_functions", true, false, "Allow usage of deprecated error prone window functions (neighbor, runningAccumulate, runningDifferenceStartingWithFirstValue, runningDifference)"},
|
||||
{"allow_experimental_join_condition", false, false, "Support join with inequal conditions which involve columns from both left and right table. e.g. t1.y < t2.y."},
|
||||
|
@ -14,6 +14,15 @@ namespace ProfileEvents
|
||||
{
|
||||
extern const Event RemoteWriteThrottlerBytes;
|
||||
extern const Event RemoteWriteThrottlerSleepMicroseconds;
|
||||
|
||||
extern const Event AzureUpload;
|
||||
extern const Event AzureStageBlock;
|
||||
extern const Event AzureCommitBlockList;
|
||||
|
||||
extern const Event DiskAzureUpload;
|
||||
extern const Event DiskAzureStageBlock;
|
||||
extern const Event DiskAzureCommitBlockList;
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
@ -134,6 +143,10 @@ void WriteBufferFromAzureBlobStorage::preFinalize()
|
||||
/// then we use single part upload instead of multi part upload
|
||||
if (block_ids.empty() && detached_part_data.size() == 1 && detached_part_data.front().data_size <= max_single_part_upload_size)
|
||||
{
|
||||
ProfileEvents::increment(ProfileEvents::AzureUpload);
|
||||
if (blob_container_client->GetClickhouseOptions().IsClientForDisk)
|
||||
ProfileEvents::increment(ProfileEvents::DiskAzureUpload);
|
||||
|
||||
auto part_data = std::move(detached_part_data.front());
|
||||
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
|
||||
Azure::Core::IO::MemoryBodyStream memory_stream(reinterpret_cast<const uint8_t *>(part_data.memory.data()), part_data.data_size);
|
||||
@ -164,6 +177,10 @@ void WriteBufferFromAzureBlobStorage::finalizeImpl()
|
||||
if (!block_ids.empty())
|
||||
{
|
||||
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
|
||||
ProfileEvents::increment(ProfileEvents::AzureCommitBlockList);
|
||||
if (blob_container_client->GetClickhouseOptions().IsClientForDisk)
|
||||
ProfileEvents::increment(ProfileEvents::DiskAzureCommitBlockList);
|
||||
|
||||
execWithRetry([&](){ block_blob_client.CommitBlockList(block_ids); }, max_unexpected_write_error_retries);
|
||||
LOG_TRACE(log, "Committed {} blocks for blob `{}`", block_ids.size(), blob_path);
|
||||
}
|
||||
@ -269,6 +286,10 @@ void WriteBufferFromAzureBlobStorage::writePart(WriteBufferFromAzureBlobStorage:
|
||||
auto & data_block_id = std::get<0>(*worker_data);
|
||||
auto block_blob_client = blob_container_client->GetBlockBlobClient(blob_path);
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::AzureStageBlock);
|
||||
if (blob_container_client->GetClickhouseOptions().IsClientForDisk)
|
||||
ProfileEvents::increment(ProfileEvents::DiskAzureStageBlock);
|
||||
|
||||
Azure::Core::IO::MemoryBodyStream memory_stream(reinterpret_cast<const uint8_t *>(std::get<1>(*worker_data).memory.data()), data_size);
|
||||
execWithRetry([&](){ block_blob_client.StageBlock(data_block_id, memory_stream); }, max_unexpected_write_error_retries, data_size);
|
||||
};
|
||||
|
@ -75,6 +75,7 @@ struct RelativePathWithMetadata
|
||||
virtual std::string getPath() const { return relative_path; }
|
||||
virtual bool isArchive() const { return false; }
|
||||
virtual std::string getPathToArchive() const { throw Exception(ErrorCodes::LOGICAL_ERROR, "Not an archive"); }
|
||||
virtual size_t fileSizeInArchive() const { throw Exception(ErrorCodes::LOGICAL_ERROR, "Not an archive"); }
|
||||
};
|
||||
|
||||
struct ObjectKeyWithMetadata
|
||||
|
@ -16,6 +16,7 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
||||
extern const int PARAMETER_OUT_OF_BOUND;
|
||||
extern const int TOO_FEW_ARGUMENTS_FOR_FUNCTION;
|
||||
}
|
||||
|
||||
@ -146,6 +147,9 @@ private:
|
||||
const auto pos = pos_col_const->getUInt(0);
|
||||
if (pos < 8 * sizeof(ValueType))
|
||||
mask = mask | (ValueType(1) << pos);
|
||||
else
|
||||
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
|
||||
"The bit position argument {} is out of bounds for number", static_cast<UInt64>(pos));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -186,13 +190,20 @@ private:
|
||||
for (const auto i : collections::range(0, mask.size()))
|
||||
if (pos[i] < 8 * sizeof(ValueType))
|
||||
mask[i] = mask[i] | (ValueType(1) << pos[i]);
|
||||
else
|
||||
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
|
||||
"The bit position argument {} is out of bounds for number", static_cast<UInt64>(pos[i]));
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (const auto pos_col_const = checkAndGetColumnConst<ColumnVector<PosType>>(pos_col_untyped))
|
||||
{
|
||||
const auto & pos = pos_col_const->template getValue<PosType>();
|
||||
const auto new_mask = pos < 8 * sizeof(ValueType) ? ValueType(1) << pos : 0;
|
||||
if (pos >= 8 * sizeof(ValueType))
|
||||
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
|
||||
"The bit position argument {} is out of bounds for number", static_cast<UInt64>(pos));
|
||||
|
||||
const auto new_mask = ValueType(1) << pos;
|
||||
|
||||
for (const auto i : collections::range(0, mask.size()))
|
||||
mask[i] = mask[i] | new_mask;
|
||||
|
@ -8,6 +8,7 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
extern const int PARAMETER_OUT_OF_BOUND;
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -21,12 +22,21 @@ struct BitTestImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
NO_SANITIZE_UNDEFINED static Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
static Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "bitTest is not implemented for big integers as second argument");
|
||||
else
|
||||
return (typename NumberTraits::ToInteger<A>::Type(a) >> typename NumberTraits::ToInteger<B>::Type(b)) & 1;
|
||||
{
|
||||
typename NumberTraits::ToInteger<A>::Type a_int = a;
|
||||
typename NumberTraits::ToInteger<B>::Type b_int = b;
|
||||
const auto max_position = static_cast<decltype(b)>((8 * sizeof(a)) - 1);
|
||||
if (b_int > max_position || b_int < 0)
|
||||
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
|
||||
"The bit position argument needs to a positive value and less or equal to {} for integer {}",
|
||||
std::to_string(max_position), std::to_string(a_int));
|
||||
return (a_int >> b_int) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
@ -16,10 +16,12 @@
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event AzureCopyObject;
|
||||
extern const Event AzureUploadPart;
|
||||
extern const Event AzureStageBlock;
|
||||
extern const Event AzureCommitBlockList;
|
||||
|
||||
extern const Event DiskAzureCopyObject;
|
||||
extern const Event DiskAzureUploadPart;
|
||||
extern const Event DiskAzureStageBlock;
|
||||
extern const Event DiskAzureCommitBlockList;
|
||||
}
|
||||
|
||||
|
||||
@ -156,6 +158,10 @@ namespace
|
||||
void completeMultipartUpload()
|
||||
{
|
||||
auto block_blob_client = client->GetBlockBlobClient(dest_blob);
|
||||
ProfileEvents::increment(ProfileEvents::AzureCommitBlockList);
|
||||
if (client->GetClickhouseOptions().IsClientForDisk)
|
||||
ProfileEvents::increment(ProfileEvents::DiskAzureCommitBlockList);
|
||||
|
||||
block_blob_client.CommitBlockList(block_ids);
|
||||
}
|
||||
|
||||
@ -259,9 +265,9 @@ namespace
|
||||
|
||||
void processUploadPartRequest(UploadPartTask & task)
|
||||
{
|
||||
ProfileEvents::increment(ProfileEvents::AzureUploadPart);
|
||||
ProfileEvents::increment(ProfileEvents::AzureStageBlock);
|
||||
if (client->GetClickhouseOptions().IsClientForDisk)
|
||||
ProfileEvents::increment(ProfileEvents::DiskAzureUploadPart);
|
||||
ProfileEvents::increment(ProfileEvents::DiskAzureStageBlock);
|
||||
|
||||
auto block_blob_client = client->GetBlockBlobClient(dest_blob);
|
||||
auto read_buffer = std::make_unique<LimitSeekableReadBuffer>(create_read_buffer(), task.part_offset, task.part_size);
|
||||
@ -333,7 +339,6 @@ void copyAzureBlobStorageFile(
|
||||
const ReadSettings & read_settings,
|
||||
ThreadPoolCallbackRunnerUnsafe<void> schedule)
|
||||
{
|
||||
|
||||
if (settings->use_native_copy)
|
||||
{
|
||||
LOG_TRACE(getLogger("copyAzureBlobStorageFile"), "Copying Blob: {} from Container: {} using native copy", src_container_for_logging, src_blob);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <Interpreters/Context.h>
|
||||
#include <IO/SwapHelper.h>
|
||||
#include <IO/ReadBufferFromFile.h>
|
||||
#include <IO/EmptyReadBuffer.h>
|
||||
#include <IO/ReadBufferFromEmptyFile.h>
|
||||
|
||||
#include <base/scope_guard.h>
|
||||
|
||||
@ -134,7 +134,7 @@ std::unique_ptr<ReadBuffer> WriteBufferToFileSegment::getReadBufferImpl()
|
||||
if (file_segment->getDownloadedSize() > 0)
|
||||
return std::make_unique<ReadBufferFromFile>(file_segment->getPath());
|
||||
else
|
||||
return std::make_unique<EmptyReadBuffer>();
|
||||
return std::make_unique<ReadBufferFromEmptyFile>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ ColumnsDescription ObjectStorageQueueLogElement::getColumnsDescription()
|
||||
{"status", status_datatype, "Status of the processing file"},
|
||||
{"processing_start_time", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeDateTime>()), "Time of the start of processing the file"},
|
||||
{"processing_end_time", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeDateTime>()), "Time of the end of processing the file"},
|
||||
{"ProfileEvents", std::make_shared<DataTypeMap>(std::make_shared<DataTypeString>(), std::make_shared<DataTypeUInt64>()), "Profile events collected while loading this file"},
|
||||
{"exception", std::make_shared<DataTypeString>(), "Exception message if happened"},
|
||||
};
|
||||
}
|
||||
@ -64,8 +63,6 @@ void ObjectStorageQueueLogElement::appendToBlock(MutableColumns & columns) const
|
||||
else
|
||||
columns[i++]->insertDefault();
|
||||
|
||||
ProfileEvents::dumpToMapColumn(counters_snapshot, columns[i++].get(), true);
|
||||
|
||||
columns[i++]->insert(exception);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ struct ObjectStorageQueueLogElement
|
||||
Failed,
|
||||
};
|
||||
ObjectStorageQueueStatus status;
|
||||
ProfileEvents::Counters::Snapshot counters_snapshot;
|
||||
time_t processing_start_time;
|
||||
time_t processing_end_time;
|
||||
std::string exception;
|
||||
|
@ -112,7 +112,7 @@ void ASTAuthenticationData::formatImpl(const FormatSettings & settings, FormatSt
|
||||
}
|
||||
case AuthenticationType::SSL_CERTIFICATE:
|
||||
{
|
||||
prefix = "CN";
|
||||
prefix = ssl_cert_subject_type.value();
|
||||
parameters = true;
|
||||
break;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
|
||||
std::optional<String> getPassword() const;
|
||||
std::optional<String> getSalt() const;
|
||||
std::optional<String> ssl_cert_subject_type; /// CN or SubjectAltName
|
||||
|
||||
/// If type is empty we use the default password type.
|
||||
/// AuthenticationType::NO_PASSWORD is specified explicitly.
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <Parsers/Access/ASTUserNameWithHost.h>
|
||||
#include <Parsers/Access/ASTAuthenticationData.h>
|
||||
#include <Common/quoteString.h>
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <IO/Operators.h>
|
||||
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <base/range.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <base/insertAtEnd.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace DB
|
||||
@ -65,7 +64,7 @@ namespace
|
||||
bool expect_hash = false;
|
||||
bool expect_ldap_server_name = false;
|
||||
bool expect_kerberos_realm = false;
|
||||
bool expect_common_names = false;
|
||||
bool expect_ssl_cert_subjects = false;
|
||||
bool expect_public_ssh_key = false;
|
||||
bool expect_http_auth_server = false;
|
||||
|
||||
@ -82,7 +81,7 @@ namespace
|
||||
else if (check_type == AuthenticationType::KERBEROS)
|
||||
expect_kerberos_realm = true;
|
||||
else if (check_type == AuthenticationType::SSL_CERTIFICATE)
|
||||
expect_common_names = true;
|
||||
expect_ssl_cert_subjects = true;
|
||||
else if (check_type == AuthenticationType::SSH_KEY)
|
||||
expect_public_ssh_key = true;
|
||||
else if (check_type == AuthenticationType::HTTP)
|
||||
@ -122,9 +121,10 @@ namespace
|
||||
|
||||
ASTPtr value;
|
||||
ASTPtr parsed_salt;
|
||||
ASTPtr common_names;
|
||||
ASTPtr public_ssh_keys;
|
||||
ASTPtr http_auth_scheme;
|
||||
ASTPtr ssl_cert_subjects;
|
||||
std::optional<String> ssl_cert_subject_type;
|
||||
|
||||
if (expect_password || expect_hash)
|
||||
{
|
||||
@ -153,12 +153,19 @@ namespace
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (expect_common_names)
|
||||
else if (expect_ssl_cert_subjects)
|
||||
{
|
||||
if (!ParserKeyword{Keyword::CN}.ignore(pos, expected))
|
||||
for (const Keyword &keyword : {Keyword::CN, Keyword::SAN})
|
||||
if (ParserKeyword{keyword}.ignore(pos, expected))
|
||||
{
|
||||
ssl_cert_subject_type = toStringView(keyword);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ssl_cert_subject_type)
|
||||
return false;
|
||||
|
||||
if (!ParserList{std::make_unique<ParserStringAndSubstitution>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, common_names, expected))
|
||||
if (!ParserList{std::make_unique<ParserStringAndSubstitution>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, ssl_cert_subjects, expected))
|
||||
return false;
|
||||
}
|
||||
else if (expect_public_ssh_key)
|
||||
@ -166,7 +173,7 @@ namespace
|
||||
if (!ParserKeyword{Keyword::BY}.ignore(pos, expected))
|
||||
return false;
|
||||
|
||||
if (!ParserList{std::make_unique<ParserPublicSSHKey>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, common_names, expected))
|
||||
if (!ParserList{std::make_unique<ParserPublicSSHKey>(), std::make_unique<ParserToken>(TokenType::Comma), false}.parse(pos, public_ssh_keys, expected))
|
||||
return false;
|
||||
}
|
||||
else if (expect_http_auth_server)
|
||||
@ -195,8 +202,11 @@ namespace
|
||||
if (parsed_salt)
|
||||
auth_data->children.push_back(std::move(parsed_salt));
|
||||
|
||||
if (common_names)
|
||||
auth_data->children = std::move(common_names->children);
|
||||
if (ssl_cert_subjects)
|
||||
{
|
||||
auth_data->ssl_cert_subject_type = ssl_cert_subject_type.value();
|
||||
auth_data->children = std::move(ssl_cert_subjects->children);
|
||||
}
|
||||
|
||||
if (public_ssh_keys)
|
||||
auth_data->children = std::move(public_ssh_keys->children);
|
||||
|
@ -418,6 +418,7 @@ namespace DB
|
||||
MR_MACROS(SALT, "SALT") \
|
||||
MR_MACROS(SAMPLE_BY, "SAMPLE BY") \
|
||||
MR_MACROS(SAMPLE, "SAMPLE") \
|
||||
MR_MACROS(SAN, "SAN") \
|
||||
MR_MACROS(SCHEME, "SCHEME") \
|
||||
MR_MACROS(SECOND, "SECOND") \
|
||||
MR_MACROS(SECONDS, "SECONDS") \
|
||||
|
@ -125,7 +125,7 @@ void Chunk::addColumn(size_t position, ColumnPtr column)
|
||||
if (position >= columns.size())
|
||||
throw Exception(ErrorCodes::POSITION_OUT_OF_BOUND,
|
||||
"Position {} out of bound in Chunk::addColumn(), max position = {}",
|
||||
position, columns.size() - 1);
|
||||
position, !columns.empty() ? columns.size() - 1 : 0);
|
||||
if (empty())
|
||||
num_rows = column->size();
|
||||
else if (column->size() != num_rows)
|
||||
@ -143,7 +143,7 @@ void Chunk::erase(size_t position)
|
||||
|
||||
if (position >= columns.size())
|
||||
throw Exception(ErrorCodes::POSITION_OUT_OF_BOUND, "Position {} out of bound in Chunk::erase(), max position = {}",
|
||||
toString(position), toString(columns.size() - 1));
|
||||
toString(position), toString(!columns.empty() ? columns.size() - 1 : 0));
|
||||
|
||||
columns.erase(columns.begin() + position);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ private:
|
||||
{
|
||||
throw Exception(
|
||||
ErrorCodes::PARQUET_EXCEPTION,
|
||||
"Unsupported logical type: {} and physical type: {} for field =={}=={}",
|
||||
"Unsupported logical type: {} and physical type: {} for field `{}`{}",
|
||||
col_descriptor.logical_type()->ToString(), col_descriptor.physical_type(), col_descriptor.name(), msg);
|
||||
}
|
||||
};
|
||||
|
@ -383,7 +383,7 @@ Pipe ReadFromMergeTree::readFromPoolParallelReplicas(
|
||||
pool, std::move(algorithm), prewhere_info,
|
||||
actions_settings, block_size_copy, reader_settings);
|
||||
|
||||
auto source = std::make_shared<MergeTreeSource>(std::move(processor));
|
||||
auto source = std::make_shared<MergeTreeSource>(std::move(processor), data.getLogName());
|
||||
pipes.emplace_back(std::move(source));
|
||||
}
|
||||
|
||||
@ -482,7 +482,7 @@ Pipe ReadFromMergeTree::readFromPool(
|
||||
pool, std::move(algorithm), prewhere_info,
|
||||
actions_settings, block_size_copy, reader_settings);
|
||||
|
||||
auto source = std::make_shared<MergeTreeSource>(std::move(processor));
|
||||
auto source = std::make_shared<MergeTreeSource>(std::move(processor), data.getLogName());
|
||||
|
||||
if (i == 0)
|
||||
source->addTotalRowsApprox(total_rows);
|
||||
@ -595,7 +595,7 @@ Pipe ReadFromMergeTree::readInOrder(
|
||||
|
||||
processor->addPartLevelToChunk(isQueryWithFinal());
|
||||
|
||||
auto source = std::make_shared<MergeTreeSource>(std::move(processor));
|
||||
auto source = std::make_shared<MergeTreeSource>(std::move(processor), data.getLogName());
|
||||
if (set_total_rows_approx)
|
||||
source->addTotalRowsApprox(total_rows);
|
||||
|
||||
|
@ -37,7 +37,9 @@
|
||||
#include <base/getFQDNOrHostName.h>
|
||||
#include <base/scope_guard.h>
|
||||
#include <Server/HTTP/HTTPResponse.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include "config.h"
|
||||
|
||||
#include <Poco/Base64Decoder.h>
|
||||
@ -380,7 +382,7 @@ bool HTTPHandler::authenticateUser(
|
||||
bool has_credentials_in_query_params = params.has("user") || params.has("password");
|
||||
|
||||
std::string spnego_challenge;
|
||||
std::string certificate_common_name;
|
||||
SSLCertificateSubjects certificate_subjects;
|
||||
|
||||
if (has_auth_headers)
|
||||
{
|
||||
@ -403,11 +405,11 @@ bool HTTPHandler::authenticateUser(
|
||||
"to use SSL certificate authentication and authentication via password simultaneously");
|
||||
|
||||
if (request.havePeerCertificate())
|
||||
certificate_common_name = request.peerCertificate().commonName();
|
||||
certificate_subjects = extractSSLCertificateSubjects(request.peerCertificate());
|
||||
|
||||
if (certificate_common_name.empty())
|
||||
if (certificate_subjects.empty())
|
||||
throw Exception(ErrorCodes::AUTHENTICATION_FAILED,
|
||||
"Invalid authentication: SSL certificate authentication requires nonempty certificate's Common Name");
|
||||
"Invalid authentication: SSL certificate authentication requires nonempty certificate's Common Name or Subject Alternative Name");
|
||||
#else
|
||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED,
|
||||
"SSL certificate authentication disabled because ClickHouse was built without SSL library");
|
||||
@ -451,10 +453,10 @@ bool HTTPHandler::authenticateUser(
|
||||
password = params.get("password", "");
|
||||
}
|
||||
|
||||
if (!certificate_common_name.empty())
|
||||
if (!certificate_subjects.empty())
|
||||
{
|
||||
if (!request_credentials)
|
||||
request_credentials = std::make_unique<SSLCertificateCredentials>(user, certificate_common_name);
|
||||
request_credentials = std::make_unique<SSLCertificateCredentials>(user, std::move(certificate_subjects));
|
||||
|
||||
auto * certificate_credentials = dynamic_cast<SSLCertificateCredentials *>(request_credentials.get());
|
||||
if (!certificate_credentials)
|
||||
|
@ -13,11 +13,9 @@
|
||||
#include <Common/setThreadName.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <base/defines.h>
|
||||
#include <chrono>
|
||||
#include <Common/PipeFDs.h>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
#include <IO/ReadBufferFromFileDescriptor.h>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <Coordination/FourLetterCommand.h>
|
||||
#include <IO/CompressionMethod.h>
|
||||
@ -30,6 +28,11 @@
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event KeeperTotalElapsedMicroseconds;
|
||||
}
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -411,12 +414,12 @@ void KeeperTCPHandler::runImpl()
|
||||
keeper_dispatcher->registerSession(session_id, response_callback);
|
||||
|
||||
Stopwatch logging_stopwatch;
|
||||
auto operation_max_ms = keeper_dispatcher->getKeeperContext()->getCoordinationSettings()->log_slow_connection_operation_threshold_ms;
|
||||
auto log_long_operation = [&](const String & operation)
|
||||
{
|
||||
constexpr UInt64 operation_max_ms = 500;
|
||||
auto elapsed_ms = logging_stopwatch.elapsedMilliseconds();
|
||||
if (operation_max_ms < elapsed_ms)
|
||||
LOG_TEST(log, "{} for session {} took {} ms", operation, session_id, elapsed_ms);
|
||||
LOG_INFO(log, "{} for session {} took {} ms", operation, session_id, elapsed_ms);
|
||||
logging_stopwatch.restart();
|
||||
};
|
||||
|
||||
@ -611,11 +614,13 @@ void KeeperTCPHandler::updateStats(Coordination::ZooKeeperResponsePtr & response
|
||||
/// update statistics ignoring watch response and heartbeat.
|
||||
if (response->xid != Coordination::WATCH_XID && response->getOpNum() != Coordination::OpNum::Heartbeat)
|
||||
{
|
||||
Int64 elapsed = (Poco::Timestamp() - operations[response->xid]) / 1000;
|
||||
conn_stats.updateLatency(elapsed);
|
||||
Int64 elapsed = (Poco::Timestamp() - operations[response->xid]);
|
||||
ProfileEvents::increment(ProfileEvents::KeeperTotalElapsedMicroseconds, elapsed);
|
||||
Int64 elapsed_ms = elapsed / 1000;
|
||||
conn_stats.updateLatency(elapsed_ms);
|
||||
|
||||
operations.erase(response->xid);
|
||||
keeper_dispatcher->updateKeeperStatLatency(elapsed);
|
||||
keeper_dispatcher->updateKeeperStatLatency(elapsed_ms);
|
||||
|
||||
last_op.set(std::make_unique<LastOp>(LastOp{
|
||||
.name = Coordination::toString(response->getOpNum()),
|
||||
|
@ -1490,7 +1490,7 @@ void TCPHandler::receiveHello()
|
||||
try
|
||||
{
|
||||
session->authenticate(
|
||||
SSLCertificateCredentials{user, secure_socket.peerCertificate().commonName()},
|
||||
SSLCertificateCredentials{user, extractSSLCertificateSubjects(secure_socket.peerCertificate())},
|
||||
getClientAddress(client_info));
|
||||
return;
|
||||
}
|
||||
|
@ -375,6 +375,12 @@ void IMergeTreeDataPart::unloadIndex()
|
||||
index_loaded = false;
|
||||
}
|
||||
|
||||
bool IMergeTreeDataPart::isIndexLoaded() const
|
||||
{
|
||||
std::scoped_lock lock(index_mutex);
|
||||
return index_loaded;
|
||||
}
|
||||
|
||||
void IMergeTreeDataPart::setName(const String & new_name)
|
||||
{
|
||||
mutable_name = new_name;
|
||||
|
@ -369,6 +369,7 @@ public:
|
||||
void setIndex(const Columns & cols_);
|
||||
void setIndex(Columns && cols_);
|
||||
void unloadIndex();
|
||||
bool isIndexLoaded() const;
|
||||
|
||||
/// For data in RAM ('index')
|
||||
UInt64 getIndexSizeInBytes() const;
|
||||
|
@ -555,18 +555,18 @@ bool MergeTask::VerticalMergeStage::prepareVerticalMergeForAllColumns() const
|
||||
if (!reread_buf)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot read temporary file {}", ctx->rows_sources_uncompressed_write_buf->getFileName());
|
||||
|
||||
auto * reread_buffer_raw = dynamic_cast<ReadBufferFromFile *>(reread_buf.get());
|
||||
auto * reread_buffer_raw = dynamic_cast<ReadBufferFromFileBase *>(reread_buf.get());
|
||||
if (!reread_buffer_raw)
|
||||
{
|
||||
const auto & reread_buf_ref = *reread_buf;
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Expected ReadBufferFromFile, but got {}", demangle(typeid(reread_buf_ref).name()));
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Expected ReadBufferFromFileBase, but got {}", demangle(typeid(reread_buf_ref).name()));
|
||||
}
|
||||
/// Move ownership from std::unique_ptr<ReadBuffer> to std::unique_ptr<ReadBufferFromFile> for CompressedReadBufferFromFile.
|
||||
/// First, release ownership from unique_ptr to base type.
|
||||
reread_buf.release(); /// NOLINT(bugprone-unused-return-value,hicpp-ignored-remove-result): we already have the pointer value in `reread_buffer_raw`
|
||||
|
||||
/// Then, move ownership to unique_ptr to concrete type.
|
||||
std::unique_ptr<ReadBufferFromFile> reread_buffer_from_file(reread_buffer_raw);
|
||||
std::unique_ptr<ReadBufferFromFileBase> reread_buffer_from_file(reread_buffer_raw);
|
||||
|
||||
/// CompressedReadBufferFromFile expects std::unique_ptr<ReadBufferFromFile> as argument.
|
||||
ctx->rows_sources_read_buf = std::make_unique<CompressedReadBufferFromFile>(std::move(reread_buffer_from_file));
|
||||
|
@ -8608,6 +8608,38 @@ void MergeTreeData::unloadPrimaryKeys()
|
||||
}
|
||||
}
|
||||
|
||||
size_t MergeTreeData::unloadPrimaryKeysOfOutdatedParts()
|
||||
{
|
||||
/// If the method is already called from another thread, then we don't need to do anything.
|
||||
std::unique_lock lock(unload_primary_key_mutex, std::defer_lock);
|
||||
if (!lock.try_lock())
|
||||
return 0;
|
||||
|
||||
DataPartsVector parts_to_unload_index;
|
||||
|
||||
{
|
||||
auto parts_lock = lockParts();
|
||||
auto parts_range = getDataPartsStateRange(DataPartState::Outdated);
|
||||
|
||||
for (const auto & part : parts_range)
|
||||
{
|
||||
/// Outdated part may be hold by SELECT query and still needs the index.
|
||||
/// This check requires lock of index_mutex but if outdated part is unique then there is no
|
||||
/// contention on it, so it's relatively cheap and it's ok to check under a global parts lock.
|
||||
if (part.unique() && part->isIndexLoaded())
|
||||
parts_to_unload_index.push_back(part);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto & part : parts_to_unload_index)
|
||||
{
|
||||
const_cast<IMergeTreeDataPart &>(*part).unloadIndex();
|
||||
LOG_TEST(log, "Unloaded primary key for outdated part {}", part->name);
|
||||
}
|
||||
|
||||
return parts_to_unload_index.size();
|
||||
}
|
||||
|
||||
void MergeTreeData::verifySortingKey(const KeyDescription & sorting_key)
|
||||
{
|
||||
/// Aggregate functions already forbidden, but SimpleAggregateFunction are not
|
||||
|
@ -1096,8 +1096,13 @@ public:
|
||||
|
||||
static VirtualColumnsDescription createVirtuals(const StorageInMemoryMetadata & metadata);
|
||||
|
||||
/// Unloads primary keys of all parts.
|
||||
void unloadPrimaryKeys();
|
||||
|
||||
/// Unloads primary keys of outdated parts that are not used by any query.
|
||||
/// Returns the number of parts for which index was unloaded.
|
||||
size_t unloadPrimaryKeysOfOutdatedParts();
|
||||
|
||||
protected:
|
||||
friend class IMergeTreeDataPart;
|
||||
friend class MergeTreeDataMergerMutator;
|
||||
@ -1260,6 +1265,8 @@ protected:
|
||||
std::mutex grab_old_parts_mutex;
|
||||
/// The same for clearOldTemporaryDirectories.
|
||||
std::mutex clear_old_temporary_directories_mutex;
|
||||
/// The same for unloadPrimaryKeysOfOutdatedParts.
|
||||
std::mutex unload_primary_key_mutex;
|
||||
|
||||
void checkProperties(
|
||||
const StorageInMemoryMetadata & new_metadata,
|
||||
|
@ -133,9 +133,8 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
MergeTreeSource::MergeTreeSource(MergeTreeSelectProcessorPtr processor_)
|
||||
: ISource(processor_->getHeader())
|
||||
, processor(std::move(processor_))
|
||||
MergeTreeSource::MergeTreeSource(MergeTreeSelectProcessorPtr processor_, const std::string & log_name_)
|
||||
: ISource(processor_->getHeader()), processor(std::move(processor_)), log_name(log_name_)
|
||||
{
|
||||
#if defined(OS_LINUX)
|
||||
if (processor->getSettings().use_asynchronous_read_from_pool)
|
||||
@ -207,7 +206,7 @@ std::optional<Chunk> MergeTreeSource::tryGenerate()
|
||||
|
||||
try
|
||||
{
|
||||
OpenTelemetry::SpanHolder span{"MergeTreeSource::tryGenerate()"};
|
||||
OpenTelemetry::SpanHolder span{fmt::format("MergeTreeSource({})::tryGenerate", log_name)};
|
||||
holder->setResult(processor->read());
|
||||
}
|
||||
catch (...)
|
||||
@ -222,7 +221,7 @@ std::optional<Chunk> MergeTreeSource::tryGenerate()
|
||||
}
|
||||
#endif
|
||||
|
||||
OpenTelemetry::SpanHolder span{"MergeTreeSource::tryGenerate()"};
|
||||
OpenTelemetry::SpanHolder span{fmt::format("MergeTreeSource({})::tryGenerate", log_name)};
|
||||
return processReadResult(processor->read());
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ struct ChunkAndProgress;
|
||||
class MergeTreeSource final : public ISource
|
||||
{
|
||||
public:
|
||||
explicit MergeTreeSource(MergeTreeSelectProcessorPtr processor_);
|
||||
explicit MergeTreeSource(MergeTreeSelectProcessorPtr processor_, const std::string & log_name_);
|
||||
~MergeTreeSource() override;
|
||||
|
||||
std::string getName() const override;
|
||||
@ -30,6 +30,7 @@ protected:
|
||||
|
||||
private:
|
||||
MergeTreeSelectProcessorPtr processor;
|
||||
const std::string log_name;
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
struct AsyncReadingState;
|
||||
|
@ -175,6 +175,8 @@ Float32 ReplicatedMergeTreeCleanupThread::iterate()
|
||||
cleaned_part_like += storage.clearEmptyParts();
|
||||
}
|
||||
|
||||
cleaned_part_like += storage.unloadPrimaryKeysOfOutdatedParts();
|
||||
|
||||
/// We need to measure the number of removed objects somehow (for better scheduling),
|
||||
/// but just summing the number of removed async blocks, logs, and empty parts does not make any sense.
|
||||
/// So we are trying to (approximately) measure the number of inserted blocks/parts, so we will be able to compare apples to apples.
|
||||
|
@ -4,19 +4,41 @@
|
||||
#include <set>
|
||||
|
||||
#if USE_AWS_S3 && USE_PARQUET
|
||||
#include <parquet/file_reader.h>
|
||||
|
||||
#include <Common/logger_useful.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Formats/FormatFactory.h>
|
||||
|
||||
#include <IO/ReadBufferFromFileBase.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Storages/ObjectStorage/DataLakes/Common.h>
|
||||
|
||||
#include <Processors/Formats/Impl/ArrowBufferedStreams.h>
|
||||
#include <Processors/Formats/Impl/ParquetBlockInputFormat.h>
|
||||
#include <Processors/Formats/Impl/ArrowColumnToCHColumn.h>
|
||||
#include <Formats/FormatFactory.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <IO/ReadBufferFromFileBase.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
|
||||
#include <DataTypes/DataTypeFactory.h>
|
||||
#include <DataTypes/DataTypeArray.h>
|
||||
#include <DataTypes/DataTypeDate.h>
|
||||
#include <DataTypes/DataTypeDateTime64.h>
|
||||
#include <DataTypes/DataTypeFixedString.h>
|
||||
#include <DataTypes/DataTypeMap.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
#include <DataTypes/DataTypeTuple.h>
|
||||
#include <DataTypes/DataTypeUUID.h>
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <parquet/file_reader.h>
|
||||
#include <parquet/arrow/reader.h>
|
||||
#include <Storages/ObjectStorage/DataLakes/Common.h>
|
||||
#include <Poco/JSON/Array.h>
|
||||
#include <Poco/JSON/Object.h>
|
||||
#include <Poco/JSON/Parser.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -25,10 +47,14 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int INCORRECT_DATA;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int LOGICAL_ERROR;
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
struct DeltaLakeMetadata::Impl
|
||||
struct DeltaLakeMetadataImpl
|
||||
{
|
||||
using ConfigurationPtr = DeltaLakeMetadata::ConfigurationPtr;
|
||||
|
||||
ObjectStoragePtr object_storage;
|
||||
ConfigurationPtr configuration;
|
||||
ContextPtr context;
|
||||
@ -37,7 +63,7 @@ struct DeltaLakeMetadata::Impl
|
||||
* Useful links:
|
||||
* - https://github.com/delta-io/delta/blob/master/PROTOCOL.md#data-files
|
||||
*/
|
||||
Impl(ObjectStoragePtr object_storage_,
|
||||
DeltaLakeMetadataImpl(ObjectStoragePtr object_storage_,
|
||||
ConfigurationPtr configuration_,
|
||||
ContextPtr context_)
|
||||
: object_storage(object_storage_)
|
||||
@ -74,9 +100,17 @@ struct DeltaLakeMetadata::Impl
|
||||
* An action changes one aspect of the table's state, for example, adding or removing a file.
|
||||
* Note: it is not a valid json, but a list of json's, so we read it in a while cycle.
|
||||
*/
|
||||
std::set<String> processMetadataFiles()
|
||||
struct DeltaLakeMetadata
|
||||
{
|
||||
NamesAndTypesList schema;
|
||||
Strings data_files;
|
||||
DataLakePartitionColumns partition_columns;
|
||||
};
|
||||
DeltaLakeMetadata processMetadataFiles()
|
||||
{
|
||||
std::set<String> result_files;
|
||||
NamesAndTypesList current_schema;
|
||||
DataLakePartitionColumns current_partition_columns;
|
||||
const auto checkpoint_version = getCheckpointIfExists(result_files);
|
||||
|
||||
if (checkpoint_version)
|
||||
@ -90,7 +124,7 @@ struct DeltaLakeMetadata::Impl
|
||||
if (!object_storage->exists(StoredObject(file_path)))
|
||||
break;
|
||||
|
||||
processMetadataFile(file_path, result_files);
|
||||
processMetadataFile(file_path, current_schema, current_partition_columns, result_files);
|
||||
}
|
||||
|
||||
LOG_TRACE(
|
||||
@ -101,10 +135,10 @@ struct DeltaLakeMetadata::Impl
|
||||
{
|
||||
const auto keys = listFiles(*object_storage, *configuration, deltalake_metadata_directory, metadata_file_suffix);
|
||||
for (const String & key : keys)
|
||||
processMetadataFile(key, result_files);
|
||||
processMetadataFile(key, current_schema, current_partition_columns, result_files);
|
||||
}
|
||||
|
||||
return result_files;
|
||||
return DeltaLakeMetadata{current_schema, Strings(result_files.begin(), result_files.end()), current_partition_columns};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,10 +170,20 @@ struct DeltaLakeMetadata::Impl
|
||||
* \"nullCount\":{\"col-6c990940-59bb-4709-8f2e-17083a82c01a\":0,\"col-763cd7e2-7627-4d8e-9fb7-9e85d0c8845b\":0}}"}}
|
||||
* "
|
||||
*/
|
||||
void processMetadataFile(const String & key, std::set<String> & result) const
|
||||
|
||||
/// Read metadata file and fill `file_schema`, `file_parition_columns`, `result`.
|
||||
/// `result` is a list of data files.
|
||||
/// `file_schema` is a common schema for all files.
|
||||
/// Schema evolution is not supported, so we check that all files have the same schema.
|
||||
/// `file_partiion_columns` is information about partition columns of data files.
|
||||
void processMetadataFile(
|
||||
const String & metadata_file_path,
|
||||
NamesAndTypesList & file_schema,
|
||||
DataLakePartitionColumns & file_partition_columns,
|
||||
std::set<String> & result)
|
||||
{
|
||||
auto read_settings = context->getReadSettings();
|
||||
auto buf = object_storage->readObject(StoredObject(key), read_settings);
|
||||
auto buf = object_storage->readObject(StoredObject(metadata_file_path), read_settings);
|
||||
|
||||
char c;
|
||||
while (!buf->eof())
|
||||
@ -157,20 +201,239 @@ struct DeltaLakeMetadata::Impl
|
||||
if (json_str.empty())
|
||||
continue;
|
||||
|
||||
const JSON json(json_str);
|
||||
if (json.has("add"))
|
||||
Poco::JSON::Parser parser;
|
||||
Poco::Dynamic::Var json = parser.parse(json_str);
|
||||
Poco::JSON::Object::Ptr object = json.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
// std::ostringstream oss; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
|
||||
// object->stringify(oss);
|
||||
// LOG_TEST(log, "Metadata: {}", oss.str());
|
||||
|
||||
if (object->has("add"))
|
||||
{
|
||||
const auto path = json["add"]["path"].getString();
|
||||
result.insert(std::filesystem::path(configuration->getPath()) / path);
|
||||
auto add_object = object->get("add").extract<Poco::JSON::Object::Ptr>();
|
||||
auto path = add_object->getValue<String>("path");
|
||||
result.insert(fs::path(configuration->getPath()) / path);
|
||||
|
||||
auto filename = fs::path(path).filename().string();
|
||||
auto it = file_partition_columns.find(filename);
|
||||
if (it == file_partition_columns.end())
|
||||
{
|
||||
if (add_object->has("partitionValues"))
|
||||
{
|
||||
auto partition_values = add_object->get("partitionValues").extract<Poco::JSON::Object::Ptr>();
|
||||
if (partition_values->size())
|
||||
{
|
||||
auto & current_partition_columns = file_partition_columns[filename];
|
||||
for (const auto & partition_name : partition_values->getNames())
|
||||
{
|
||||
const auto value = partition_values->getValue<String>(partition_name);
|
||||
auto name_and_type = file_schema.tryGetByName(partition_name);
|
||||
if (!name_and_type)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "No such column in schema: {}", partition_name);
|
||||
|
||||
auto field = getFieldValue(value, name_and_type->type);
|
||||
current_partition_columns.emplace_back(*name_and_type, field);
|
||||
|
||||
LOG_TEST(log, "Partition {} value is {} (for {})", partition_name, value, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (json.has("remove"))
|
||||
else if (object->has("remove"))
|
||||
{
|
||||
const auto path = json["remove"]["path"].getString();
|
||||
result.erase(std::filesystem::path(configuration->getPath()) / path);
|
||||
auto path = object->get("remove").extract<Poco::JSON::Object::Ptr>()->getValue<String>("path");
|
||||
result.erase(fs::path(configuration->getPath()) / path);
|
||||
}
|
||||
if (object->has("metaData"))
|
||||
{
|
||||
const auto metadata_object = object->get("metaData").extract<Poco::JSON::Object::Ptr>();
|
||||
const auto schema_object = metadata_object->getValue<String>("schemaString");
|
||||
|
||||
Poco::JSON::Parser p;
|
||||
Poco::Dynamic::Var fields_json = parser.parse(schema_object);
|
||||
Poco::JSON::Object::Ptr fields_object = fields_json.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
const auto fields = fields_object->get("fields").extract<Poco::JSON::Array::Ptr>();
|
||||
NamesAndTypesList current_schema;
|
||||
for (size_t i = 0; i < fields->size(); ++i)
|
||||
{
|
||||
const auto field = fields->getObject(static_cast<UInt32>(i));
|
||||
auto column_name = field->getValue<String>("name");
|
||||
auto type = field->getValue<String>("type");
|
||||
auto is_nullable = field->getValue<bool>("nullable");
|
||||
|
||||
std::string physical_name;
|
||||
auto schema_metadata_object = field->get("metadata").extract<Poco::JSON::Object::Ptr>();
|
||||
if (schema_metadata_object->has("delta.columnMapping.physicalName"))
|
||||
physical_name = schema_metadata_object->getValue<String>("delta.columnMapping.physicalName");
|
||||
else
|
||||
physical_name = column_name;
|
||||
|
||||
LOG_TEST(log, "Found column: {}, type: {}, nullable: {}, physical name: {}",
|
||||
column_name, type, is_nullable, physical_name);
|
||||
|
||||
current_schema.push_back({physical_name, getFieldType(field, "type", is_nullable)});
|
||||
}
|
||||
|
||||
if (file_schema.empty())
|
||||
{
|
||||
file_schema = current_schema;
|
||||
}
|
||||
else if (file_schema != current_schema)
|
||||
{
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED,
|
||||
"Reading from files with different schema is not possible "
|
||||
"({} is different from {})",
|
||||
file_schema.toString(), current_schema.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataTypePtr getFieldType(const Poco::JSON::Object::Ptr & field, const String & type_key, bool is_nullable)
|
||||
{
|
||||
if (field->isObject(type_key))
|
||||
return getComplexTypeFromObject(field->getObject(type_key));
|
||||
|
||||
auto type = field->get(type_key);
|
||||
if (type.isString())
|
||||
{
|
||||
const String & type_name = type.extract<String>();
|
||||
auto data_type = getSimpleTypeByName(type_name);
|
||||
return is_nullable ? makeNullable(data_type) : data_type;
|
||||
}
|
||||
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unexpected 'type' field: {}", type.toString());
|
||||
}
|
||||
|
||||
Field getFieldValue(const String & value, DataTypePtr data_type)
|
||||
{
|
||||
DataTypePtr check_type;
|
||||
if (data_type->isNullable())
|
||||
check_type = static_cast<const DataTypeNullable *>(data_type.get())->getNestedType();
|
||||
else
|
||||
check_type = data_type;
|
||||
|
||||
WhichDataType which(check_type->getTypeId());
|
||||
if (which.isStringOrFixedString())
|
||||
return value;
|
||||
else if (which.isInt8())
|
||||
return parse<Int8>(value);
|
||||
else if (which.isUInt8())
|
||||
return parse<UInt8>(value);
|
||||
else if (which.isInt16())
|
||||
return parse<Int16>(value);
|
||||
else if (which.isUInt16())
|
||||
return parse<UInt16>(value);
|
||||
else if (which.isInt32())
|
||||
return parse<Int32>(value);
|
||||
else if (which.isUInt32())
|
||||
return parse<UInt32>(value);
|
||||
else if (which.isInt64())
|
||||
return parse<Int64>(value);
|
||||
else if (which.isUInt64())
|
||||
return parse<UInt64>(value);
|
||||
else if (which.isFloat32())
|
||||
return parse<Float32>(value);
|
||||
else if (which.isFloat64())
|
||||
return parse<Float64>(value);
|
||||
else if (which.isDate())
|
||||
return UInt16{LocalDate{std::string(value)}.getDayNum()};
|
||||
else if (which.isDate32())
|
||||
return Int32{LocalDate{std::string(value)}.getExtenedDayNum()};
|
||||
else if (which.isDateTime64())
|
||||
{
|
||||
ReadBufferFromString in(value);
|
||||
DateTime64 time = 0;
|
||||
readDateTime64Text(time, 6, in, assert_cast<const DataTypeDateTime64 *>(data_type.get())->getTimeZone());
|
||||
return time;
|
||||
}
|
||||
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unsupported DeltaLake type for {}", check_type->getColumnType());
|
||||
}
|
||||
|
||||
DataTypePtr getSimpleTypeByName(const String & type_name)
|
||||
{
|
||||
/// https://github.com/delta-io/delta/blob/master/PROTOCOL.md#primitive-types
|
||||
|
||||
if (type_name == "string" || type_name == "binary")
|
||||
return std::make_shared<DataTypeString>();
|
||||
if (type_name == "long")
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
if (type_name == "integer")
|
||||
return std::make_shared<DataTypeInt32>();
|
||||
if (type_name == "short")
|
||||
return std::make_shared<DataTypeInt16>();
|
||||
if (type_name == "byte")
|
||||
return std::make_shared<DataTypeInt8>();
|
||||
if (type_name == "float")
|
||||
return std::make_shared<DataTypeFloat32>();
|
||||
if (type_name == "double")
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
if (type_name == "boolean")
|
||||
return DataTypeFactory::instance().get("Bool");
|
||||
if (type_name == "date")
|
||||
return std::make_shared<DataTypeDate32>();
|
||||
if (type_name == "timestamp")
|
||||
return std::make_shared<DataTypeDateTime64>(6);
|
||||
if (type_name.starts_with("decimal(") && type_name.ends_with(')'))
|
||||
{
|
||||
ReadBufferFromString buf(std::string_view(type_name.begin() + 8, type_name.end() - 1));
|
||||
size_t precision;
|
||||
size_t scale;
|
||||
readIntText(precision, buf);
|
||||
skipWhitespaceIfAny(buf);
|
||||
assertChar(',', buf);
|
||||
skipWhitespaceIfAny(buf);
|
||||
tryReadIntText(scale, buf);
|
||||
return createDecimal<DataTypeDecimal>(precision, scale);
|
||||
}
|
||||
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unsupported DeltaLake type: {}", type_name);
|
||||
}
|
||||
|
||||
DataTypePtr getComplexTypeFromObject(const Poco::JSON::Object::Ptr & type)
|
||||
{
|
||||
String type_name = type->getValue<String>("type");
|
||||
|
||||
if (type_name == "struct")
|
||||
{
|
||||
DataTypes element_types;
|
||||
Names element_names;
|
||||
auto fields = type->get("fields").extract<Poco::JSON::Array::Ptr>();
|
||||
element_types.reserve(fields->size());
|
||||
element_names.reserve(fields->size());
|
||||
for (size_t i = 0; i != fields->size(); ++i)
|
||||
{
|
||||
auto field = fields->getObject(static_cast<Int32>(i));
|
||||
element_names.push_back(field->getValue<String>("name"));
|
||||
auto required = field->getValue<bool>("required");
|
||||
element_types.push_back(getFieldType(field, "type", required));
|
||||
}
|
||||
|
||||
return std::make_shared<DataTypeTuple>(element_types, element_names);
|
||||
}
|
||||
|
||||
if (type_name == "array")
|
||||
{
|
||||
bool is_nullable = type->getValue<bool>("containsNull");
|
||||
auto element_type = getFieldType(type, "elementType", is_nullable);
|
||||
return std::make_shared<DataTypeArray>(element_type);
|
||||
}
|
||||
|
||||
if (type_name == "map")
|
||||
{
|
||||
bool is_nullable = type->getValue<bool>("containsNull");
|
||||
auto key_type = getFieldType(type, "keyType", /* is_nullable */false);
|
||||
auto value_type = getFieldType(type, "valueType", is_nullable);
|
||||
return std::make_shared<DataTypeMap>(key_type, value_type);
|
||||
}
|
||||
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unsupported DeltaLake type: {}", type_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkpoints in delta-lake are created each 10 commits by default.
|
||||
* Latest checkpoint is written in _last_checkpoint file: _delta_log/_last_checkpoint
|
||||
@ -277,8 +540,8 @@ struct DeltaLakeMetadata::Impl
|
||||
ArrowMemoryPool::instance(),
|
||||
&reader));
|
||||
|
||||
std::shared_ptr<arrow::Schema> schema;
|
||||
THROW_ARROW_NOT_OK(reader->GetSchema(&schema));
|
||||
std::shared_ptr<arrow::Schema> file_schema;
|
||||
THROW_ARROW_NOT_OK(reader->GetSchema(&file_schema));
|
||||
|
||||
ArrowColumnToCHColumn column_reader(
|
||||
header, "Parquet",
|
||||
@ -325,18 +588,15 @@ DeltaLakeMetadata::DeltaLakeMetadata(
|
||||
ObjectStoragePtr object_storage_,
|
||||
ConfigurationPtr configuration_,
|
||||
ContextPtr context_)
|
||||
: impl(std::make_unique<Impl>(object_storage_, configuration_, context_))
|
||||
{
|
||||
}
|
||||
auto impl = DeltaLakeMetadataImpl(object_storage_, configuration_, context_);
|
||||
auto result = impl.processMetadataFiles();
|
||||
data_files = result.data_files;
|
||||
schema = result.schema;
|
||||
partition_columns = result.partition_columns;
|
||||
|
||||
Strings DeltaLakeMetadata::getDataFiles() const
|
||||
{
|
||||
if (!data_files.empty())
|
||||
return data_files;
|
||||
|
||||
auto result = impl->processMetadataFiles();
|
||||
data_files = Strings(result.begin(), result.end());
|
||||
return data_files;
|
||||
LOG_TRACE(impl.log, "Found {} data files, {} partition files, schema: {}",
|
||||
data_files.size(), partition_columns.size(), schema.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,9 +20,13 @@ public:
|
||||
ConfigurationPtr configuration_,
|
||||
ContextPtr context_);
|
||||
|
||||
Strings getDataFiles() const override;
|
||||
Strings getDataFiles() const override { return data_files; }
|
||||
|
||||
NamesAndTypesList getTableSchema() const override { return {}; }
|
||||
NamesAndTypesList getTableSchema() const override { return schema; }
|
||||
|
||||
const DataLakePartitionColumns & getPartitionColumns() const override { return partition_columns; }
|
||||
|
||||
const std::unordered_map<String, String> & getColumnNameToPhysicalNameMapping() const override { return column_name_to_physical_name; }
|
||||
|
||||
bool operator ==(const IDataLakeMetadata & other) const override
|
||||
{
|
||||
@ -41,9 +45,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
const std::shared_ptr<Impl> impl;
|
||||
mutable Strings data_files;
|
||||
NamesAndTypesList schema;
|
||||
std::unordered_map<String, String> column_name_to_physical_name;
|
||||
DataLakePartitionColumns partition_columns;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ public:
|
||||
|
||||
NamesAndTypesList getTableSchema() const override { return {}; }
|
||||
|
||||
const DataLakePartitionColumns & getPartitionColumns() const override { return partition_columns; }
|
||||
|
||||
const std::unordered_map<String, String> & getColumnNameToPhysicalNameMapping() const override { return column_name_to_physical_name; }
|
||||
|
||||
bool operator ==(const IDataLakeMetadata & other) const override
|
||||
{
|
||||
const auto * hudi_metadata = dynamic_cast<const HudiMetadata *>(&other);
|
||||
@ -46,6 +50,8 @@ private:
|
||||
const ObjectStoragePtr object_storage;
|
||||
const ConfigurationPtr configuration;
|
||||
mutable Strings data_files;
|
||||
std::unordered_map<String, String> column_name_to_physical_name;
|
||||
DataLakePartitionColumns partition_columns;
|
||||
|
||||
Strings getDataFilesImpl() const;
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <Core/Types.h>
|
||||
#include <Core/NamesAndTypes.h>
|
||||
#include "PartitionColumns.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -13,6 +14,8 @@ public:
|
||||
virtual Strings getDataFiles() const = 0;
|
||||
virtual NamesAndTypesList getTableSchema() const = 0;
|
||||
virtual bool operator==(const IDataLakeMetadata & other) const = 0;
|
||||
virtual const DataLakePartitionColumns & getPartitionColumns() const = 0;
|
||||
virtual const std::unordered_map<String, String> & getColumnNameToPhysicalNameMapping() const = 0;
|
||||
};
|
||||
using DataLakeMetadataPtr = std::unique_ptr<IDataLakeMetadata>;
|
||||
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
auto metadata = DataLakeMetadata::create(object_storage_, base_configuration, local_context);
|
||||
|
||||
auto schema_from_metadata = metadata->getTableSchema();
|
||||
if (schema_from_metadata != NamesAndTypesList{})
|
||||
if (!schema_from_metadata.empty())
|
||||
{
|
||||
return ColumnsDescription(std::move(schema_from_metadata));
|
||||
}
|
||||
@ -99,13 +99,13 @@ public:
|
||||
Storage::updateConfiguration(local_context);
|
||||
|
||||
auto new_metadata = DataLakeMetadata::create(Storage::object_storage, base_configuration, local_context);
|
||||
|
||||
if (current_metadata && *current_metadata == *new_metadata)
|
||||
return;
|
||||
|
||||
current_metadata = std::move(new_metadata);
|
||||
auto updated_configuration = base_configuration->clone();
|
||||
updated_configuration->setPaths(current_metadata->getDataFiles());
|
||||
updated_configuration->setPartitionColumns(current_metadata->getPartitionColumns());
|
||||
|
||||
Storage::configuration = updated_configuration;
|
||||
}
|
||||
@ -123,11 +123,42 @@ public:
|
||||
{
|
||||
base_configuration->format = Storage::configuration->format;
|
||||
}
|
||||
|
||||
if (current_metadata)
|
||||
{
|
||||
const auto & columns = current_metadata->getPartitionColumns();
|
||||
base_configuration->setPartitionColumns(columns);
|
||||
Storage::configuration->setPartitionColumns(columns);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ConfigurationPtr base_configuration;
|
||||
DataLakeMetadataPtr current_metadata;
|
||||
|
||||
ReadFromFormatInfo prepareReadingFromFormat(
|
||||
const Strings & requested_columns,
|
||||
const StorageSnapshotPtr & storage_snapshot,
|
||||
bool supports_subset_of_columns,
|
||||
ContextPtr local_context) override
|
||||
{
|
||||
auto info = DB::prepareReadingFromFormat(requested_columns, storage_snapshot, supports_subset_of_columns);
|
||||
if (!current_metadata)
|
||||
{
|
||||
Storage::updateConfiguration(local_context);
|
||||
current_metadata = DataLakeMetadata::create(Storage::object_storage, base_configuration, local_context);
|
||||
}
|
||||
auto column_mapping = current_metadata->getColumnNameToPhysicalNameMapping();
|
||||
if (!column_mapping.empty())
|
||||
{
|
||||
for (const auto & [column_name, physical_name] : column_mapping)
|
||||
{
|
||||
auto & column = info.format_header.getByName(column_name);
|
||||
column.name = physical_name;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
};
|
||||
|
||||
using StorageIceberg = IStorageDataLake<IcebergMetadata>;
|
||||
|
@ -82,6 +82,10 @@ public:
|
||||
/// Get table schema parsed from metadata.
|
||||
NamesAndTypesList getTableSchema() const override { return schema; }
|
||||
|
||||
const std::unordered_map<String, String> & getColumnNameToPhysicalNameMapping() const override { return column_name_to_physical_name; }
|
||||
|
||||
const DataLakePartitionColumns & getPartitionColumns() const override { return partition_columns; }
|
||||
|
||||
bool operator ==(const IDataLakeMetadata & other) const override
|
||||
{
|
||||
const auto * iceberg_metadata = dynamic_cast<const IcebergMetadata *>(&other);
|
||||
@ -104,6 +108,8 @@ private:
|
||||
Int32 current_schema_id;
|
||||
NamesAndTypesList schema;
|
||||
mutable Strings data_files;
|
||||
std::unordered_map<String, String> column_name_to_physical_name;
|
||||
DataLakePartitionColumns partition_columns;
|
||||
LoggerPtr log;
|
||||
};
|
||||
|
||||
|
19
src/Storages/ObjectStorage/DataLakes/PartitionColumns.h
Normal file
19
src/Storages/ObjectStorage/DataLakes/PartitionColumns.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <Core/NamesAndTypes.h>
|
||||
#include <Core/Field.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
struct DataLakePartitionColumn
|
||||
{
|
||||
NameAndTypePair name_and_type;
|
||||
Field value;
|
||||
|
||||
bool operator ==(const DataLakePartitionColumn & other) const = default;
|
||||
};
|
||||
|
||||
/// Data file -> partition columns
|
||||
using DataLakePartitionColumns = std::unordered_map<std::string, std::vector<DataLakePartitionColumn>>;
|
||||
|
||||
}
|
@ -203,6 +203,15 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
ReadFromFormatInfo StorageObjectStorage::prepareReadingFromFormat(
|
||||
const Strings & requested_columns,
|
||||
const StorageSnapshotPtr & storage_snapshot,
|
||||
bool supports_subset_of_columns,
|
||||
ContextPtr /* local_context */)
|
||||
{
|
||||
return DB::prepareReadingFromFormat(requested_columns, storage_snapshot, supports_subset_of_columns);
|
||||
}
|
||||
|
||||
void StorageObjectStorage::read(
|
||||
QueryPlan & query_plan,
|
||||
const Names & column_names,
|
||||
@ -222,7 +231,7 @@ void StorageObjectStorage::read(
|
||||
}
|
||||
|
||||
const auto read_from_format_info = prepareReadingFromFormat(
|
||||
column_names, storage_snapshot, supportsSubsetOfColumns(local_context));
|
||||
column_names, storage_snapshot, supportsSubsetOfColumns(local_context), local_context);
|
||||
const bool need_only_count = (query_info.optimize_trivial_count || read_from_format_info.requested_columns.empty())
|
||||
&& local_context->getSettingsRef().optimize_count_from_files;
|
||||
|
||||
@ -451,6 +460,7 @@ StorageObjectStorage::Configuration::Configuration(const Configuration & other)
|
||||
format = other.format;
|
||||
compression_method = other.compression_method;
|
||||
structure = other.structure;
|
||||
partition_columns = other.partition_columns;
|
||||
}
|
||||
|
||||
bool StorageObjectStorage::Configuration::withPartitionWildcard() const
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <Parsers/IAST_fwd.h>
|
||||
#include <Storages/prepareReadingFromFormat.h>
|
||||
#include <Processors/Formats/IInputFormat.h>
|
||||
#include <Storages/ObjectStorage/DataLakes/PartitionColumns.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -117,6 +118,12 @@ public:
|
||||
protected:
|
||||
virtual void updateConfiguration(ContextPtr local_context);
|
||||
|
||||
virtual ReadFromFormatInfo prepareReadingFromFormat(
|
||||
const Strings & requested_columns,
|
||||
const StorageSnapshotPtr & storage_snapshot,
|
||||
bool supports_subset_of_columns,
|
||||
ContextPtr local_context);
|
||||
|
||||
static std::unique_ptr<ReadBufferIterator> createReadBufferIterator(
|
||||
const ObjectStoragePtr & object_storage,
|
||||
const ConfigurationPtr & configuration,
|
||||
@ -188,6 +195,9 @@ public:
|
||||
virtual ConfigurationPtr clone() = 0;
|
||||
virtual bool isStaticConfiguration() const { return true; }
|
||||
|
||||
void setPartitionColumns(const DataLakePartitionColumns & columns) { partition_columns = columns; }
|
||||
const DataLakePartitionColumns & getPartitionColumns() const { return partition_columns; }
|
||||
|
||||
String format = "auto";
|
||||
String compression_method = "auto";
|
||||
String structure = "auto";
|
||||
@ -199,6 +209,7 @@ protected:
|
||||
void assertInitialized() const;
|
||||
|
||||
bool initialized = false;
|
||||
DataLakePartitionColumns partition_columns;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -196,13 +196,36 @@ Chunk StorageObjectStorageSource::generate()
|
||||
const auto & filename = object_info->getFileName();
|
||||
chassert(object_info->metadata);
|
||||
VirtualColumnUtils::addRequestedFileLikeStorageVirtualsToChunk(
|
||||
chunk, read_from_format_info.requested_virtual_columns,
|
||||
chunk,
|
||||
read_from_format_info.requested_virtual_columns,
|
||||
{.path = getUniqueStoragePathIdentifier(*configuration, *object_info, false),
|
||||
.size = object_info->isArchive() ? object_info->fileSizeInArchive() : object_info->metadata->size_bytes,
|
||||
.filename = &filename,
|
||||
.last_modified = object_info->metadata->last_modified});
|
||||
|
||||
const auto & partition_columns = configuration->getPartitionColumns();
|
||||
if (!partition_columns.empty() && chunk_size && chunk.hasColumns())
|
||||
{
|
||||
auto partition_values = partition_columns.find(filename);
|
||||
|
||||
for (const auto & [name_and_type, value] : partition_values->second)
|
||||
{
|
||||
.path = getUniqueStoragePathIdentifier(*configuration, *object_info, false),
|
||||
.size = object_info->metadata->size_bytes,
|
||||
.filename = &filename,
|
||||
.last_modified = object_info->metadata->last_modified
|
||||
});
|
||||
if (!read_from_format_info.source_header.has(name_and_type.name))
|
||||
continue;
|
||||
|
||||
const auto column_pos = read_from_format_info.source_header.getPositionByName(name_and_type.name);
|
||||
auto partition_column = name_and_type.type->createColumnConst(chunk.getNumRows(), value)->convertToFullColumnIfConst();
|
||||
|
||||
/// This column is filled with default value now, remove it.
|
||||
chunk.erase(column_pos);
|
||||
|
||||
/// Add correct values.
|
||||
if (chunk.hasColumns())
|
||||
chunk.addColumn(column_pos, std::move(partition_column));
|
||||
else
|
||||
chunk.addColumn(std::move(partition_column));
|
||||
}
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@ -690,10 +713,9 @@ static IArchiveReader::NameFilter createArchivePathFilter(const std::string & ar
|
||||
StorageObjectStorageSource::ArchiveIterator::ObjectInfoInArchive::ObjectInfoInArchive(
|
||||
ObjectInfoPtr archive_object_,
|
||||
const std::string & path_in_archive_,
|
||||
std::shared_ptr<IArchiveReader> archive_reader_)
|
||||
: archive_object(archive_object_)
|
||||
, path_in_archive(path_in_archive_)
|
||||
, archive_reader(archive_reader_)
|
||||
std::shared_ptr<IArchiveReader> archive_reader_,
|
||||
IArchiveReader::FileInfo && file_info_)
|
||||
: archive_object(archive_object_), path_in_archive(path_in_archive_), archive_reader(archive_reader_), file_info(file_info_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -732,6 +754,7 @@ StorageObjectStorageSource::ObjectInfoPtr
|
||||
StorageObjectStorageSource::ArchiveIterator::nextImpl(size_t processor)
|
||||
{
|
||||
std::unique_lock lock{next_mutex};
|
||||
IArchiveReader::FileInfo current_file_info{};
|
||||
while (true)
|
||||
{
|
||||
if (filter)
|
||||
@ -756,6 +779,8 @@ StorageObjectStorageSource::ArchiveIterator::nextImpl(size_t processor)
|
||||
path_in_archive = file_enumerator->getFileName();
|
||||
if (!filter(path_in_archive))
|
||||
continue;
|
||||
else
|
||||
current_file_info = file_enumerator->getFileInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -769,15 +794,19 @@ StorageObjectStorageSource::ArchiveIterator::nextImpl(size_t processor)
|
||||
archive_reader = createArchiveReader(archive_object);
|
||||
if (!archive_reader->fileExists(path_in_archive))
|
||||
continue;
|
||||
else
|
||||
current_file_info = archive_reader->getFileInfo(path_in_archive);
|
||||
}
|
||||
|
||||
auto object_in_archive = std::make_shared<ObjectInfoInArchive>(archive_object, path_in_archive, archive_reader);
|
||||
|
||||
if (read_keys != nullptr)
|
||||
read_keys->push_back(object_in_archive);
|
||||
|
||||
return object_in_archive;
|
||||
break;
|
||||
}
|
||||
|
||||
auto object_in_archive
|
||||
= std::make_shared<ObjectInfoInArchive>(archive_object, path_in_archive, archive_reader, std::move(current_file_info));
|
||||
|
||||
if (read_keys != nullptr)
|
||||
read_keys->push_back(object_in_archive);
|
||||
|
||||
return object_in_archive;
|
||||
}
|
||||
|
||||
size_t StorageObjectStorageSource::ArchiveIterator::estimatedKeysCount()
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <Processors/Executors/PullingPipelineExecutor.h>
|
||||
#include <Processors/Formats/IInputFormat.h>
|
||||
#include <Storages/ObjectStorage/StorageObjectStorage.h>
|
||||
#include <Storages/ObjectStorage/DataLakes/PartitionColumns.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -259,7 +260,8 @@ public:
|
||||
ObjectInfoInArchive(
|
||||
ObjectInfoPtr archive_object_,
|
||||
const std::string & path_in_archive_,
|
||||
std::shared_ptr<IArchiveReader> archive_reader_);
|
||||
std::shared_ptr<IArchiveReader> archive_reader_,
|
||||
IArchiveReader::FileInfo && file_info_);
|
||||
|
||||
std::string getFileName() const override
|
||||
{
|
||||
@ -278,9 +280,12 @@ public:
|
||||
|
||||
bool isArchive() const override { return true; }
|
||||
|
||||
size_t fileSizeInArchive() const override { return file_info.uncompressed_size; }
|
||||
|
||||
const ObjectInfoPtr archive_object;
|
||||
const std::string path_in_archive;
|
||||
const std::shared_ptr<IArchiveReader> archive_reader;
|
||||
const IArchiveReader::FileInfo file_info;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -34,7 +34,6 @@ public:
|
||||
std::atomic<time_t> processing_start_time = 0;
|
||||
std::atomic<time_t> processing_end_time = 0;
|
||||
std::atomic<size_t> retries = 0;
|
||||
ProfileEvents::Counters profile_counters;
|
||||
|
||||
private:
|
||||
mutable std::mutex last_exception_mutex;
|
||||
|
@ -111,10 +111,12 @@ void ObjectStorageQueueSource::FileIterator::returnForRetry(Source::ObjectInfoPt
|
||||
if (metadata->useBucketsForProcessing())
|
||||
{
|
||||
const auto bucket = metadata->getBucketForPath(object_info->relative_path);
|
||||
std::lock_guard lock(mutex);
|
||||
listed_keys_cache[bucket].keys.emplace_front(object_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
objects_to_retry.push_back(object_info);
|
||||
}
|
||||
}
|
||||
@ -509,10 +511,6 @@ Chunk ObjectStorageQueueSource::generateImpl()
|
||||
path, processed_rows_from_file);
|
||||
}
|
||||
|
||||
auto * prev_scope = CurrentThread::get().attachProfileCountersScope(&file_status->profile_counters);
|
||||
SCOPE_EXIT({ CurrentThread::get().attachProfileCountersScope(prev_scope); });
|
||||
/// FIXME: if files are compressed, profile counters update does not work fully (object storage related counters are not saved). Why?
|
||||
|
||||
try
|
||||
{
|
||||
auto timer = DB::CurrentThread::getProfileEvents().timer(ProfileEvents::ObjectStorageQueuePullMicroseconds);
|
||||
@ -714,7 +712,6 @@ void ObjectStorageQueueSource::appendLogElement(
|
||||
.file_name = filename,
|
||||
.rows_processed = processed_rows,
|
||||
.status = processed ? ObjectStorageQueueLogElement::ObjectStorageQueueStatus::Processed : ObjectStorageQueueLogElement::ObjectStorageQueueStatus::Failed,
|
||||
.counters_snapshot = file_status_.profile_counters.getPartiallyAtomicSnapshot(),
|
||||
.processing_start_time = file_status_.processing_start_time,
|
||||
.processing_end_time = file_status_.processing_end_time,
|
||||
.exception = file_status_.getException(),
|
||||
|
@ -1,11 +1,8 @@
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <stdatomic.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
#include <Storages/RocksDB/EmbeddedRocksDBBulkSink.h>
|
||||
#include <Storages/RocksDB/StorageEmbeddedRocksDB.h>
|
||||
@ -18,6 +15,7 @@
|
||||
#include <rocksdb/options.h>
|
||||
#include <rocksdb/slice.h>
|
||||
#include <rocksdb/status.h>
|
||||
#include <rocksdb/system_clock.h>
|
||||
#include <rocksdb/utilities/db_ttl.h>
|
||||
#include <Common/SipHash.h>
|
||||
#include <Common/getRandomASCIIString.h>
|
||||
@ -35,6 +33,7 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ROCKSDB_ERROR;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
static const IColumn::Permutation & getAscendingPermutation(const IColumn & column, IColumn::Permutation & perm)
|
||||
@ -156,6 +155,7 @@ std::vector<Chunk> EmbeddedRocksDBBulkSink::squash(Chunk chunk)
|
||||
return {};
|
||||
}
|
||||
|
||||
template<bool with_timestamp>
|
||||
std::pair<ColumnString::Ptr, ColumnString::Ptr> EmbeddedRocksDBBulkSink::serializeChunks(std::vector<Chunk> && input_chunks) const
|
||||
{
|
||||
auto serialized_key_column = ColumnString::create();
|
||||
@ -169,14 +169,40 @@ std::pair<ColumnString::Ptr, ColumnString::Ptr> EmbeddedRocksDBBulkSink::seriali
|
||||
WriteBufferFromVector<ColumnString::Chars> writer_key(serialized_key_data);
|
||||
WriteBufferFromVector<ColumnString::Chars> writer_value(serialized_value_data);
|
||||
FormatSettings format_settings; /// Format settings is 1.5KB, so it's not wise to create it for each row
|
||||
|
||||
/// TTL handling
|
||||
[[maybe_unused]] auto get_rocksdb_ts = [this](String & ts_string)
|
||||
{
|
||||
Int64 curtime = -1;
|
||||
auto * system_clock = storage.rocksdb_ptr->GetEnv()->GetSystemClock().get();
|
||||
rocksdb::Status st = system_clock->GetCurrentTime(&curtime);
|
||||
if (!st.ok())
|
||||
throw Exception(ErrorCodes::ROCKSDB_ERROR, "RocksDB error: {}", st.ToString());
|
||||
WriteBufferFromString buf(ts_string);
|
||||
writeBinaryLittleEndian(static_cast<Int32>(curtime), buf);
|
||||
};
|
||||
|
||||
for (auto && chunk : input_chunks)
|
||||
{
|
||||
[[maybe_unused]] String ts_string;
|
||||
if constexpr (with_timestamp)
|
||||
get_rocksdb_ts(ts_string);
|
||||
|
||||
const auto & columns = chunk.getColumns();
|
||||
auto rows = chunk.getNumRows();
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
{
|
||||
for (size_t idx = 0; idx < columns.size(); ++idx)
|
||||
serializations[idx]->serializeBinary(*columns[idx], i, idx == primary_key_pos ? writer_key : writer_value, format_settings);
|
||||
|
||||
/// Append timestamp to end of value, see rocksdb::DBWithTTLImpl::AppendTS
|
||||
if constexpr (with_timestamp)
|
||||
{
|
||||
if (ts_string.size() != sizeof(Int32))
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Invalid timestamp size: expect 4, got {}", ts_string.size());
|
||||
writeString(ts_string, writer_value);
|
||||
}
|
||||
|
||||
/// String in ColumnString must be null-terminated
|
||||
writeChar('\0', writer_key);
|
||||
writeChar('\0', writer_value);
|
||||
@ -199,7 +225,8 @@ void EmbeddedRocksDBBulkSink::consume(Chunk chunk_)
|
||||
if (chunks_to_write.empty())
|
||||
return;
|
||||
|
||||
auto [serialized_key_column, serialized_value_column] = serializeChunks(std::move(chunks_to_write));
|
||||
auto [serialized_key_column, serialized_value_column]
|
||||
= storage.ttl > 0 ? serializeChunks<true>(std::move(chunks_to_write)) : serializeChunks<false>(std::move(chunks_to_write));
|
||||
auto sst_file_path = getTemporarySSTFilePath();
|
||||
LOG_DEBUG(getLogger("EmbeddedRocksDBBulkSink"), "Writing {} rows to SST file {}", serialized_key_column->size(), sst_file_path);
|
||||
if (auto status = buildSSTFile(sst_file_path, *serialized_key_column, *serialized_value_column); !status.ok())
|
||||
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <stdatomic.h>
|
||||
#include <Processors/Sinks/SinkToStorage.h>
|
||||
#include <rocksdb/db.h>
|
||||
#include <rocksdb/status.h>
|
||||
@ -49,6 +47,7 @@ private:
|
||||
bool isEnoughSize(const std::vector<Chunk> & input_chunks) const;
|
||||
bool isEnoughSize(const Chunk & chunk) const;
|
||||
/// Serialize chunks to rocksdb key-value pairs
|
||||
template<bool with_timestamp>
|
||||
std::pair<ColumnString::Ptr, ColumnString::Ptr> serializeChunks(std::vector<Chunk> && input_chunks) const;
|
||||
|
||||
StorageEmbeddedRocksDB & storage;
|
||||
|
@ -395,11 +395,14 @@ void registerStorageJoin(StorageFactory & factory)
|
||||
else if (kind_str == "full")
|
||||
{
|
||||
if (strictness == JoinStrictness::Any)
|
||||
strictness = JoinStrictness::RightAny;
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "ANY FULL JOINs are not implemented");
|
||||
kind = JoinKind::Full;
|
||||
}
|
||||
}
|
||||
|
||||
if ((strictness == JoinStrictness::Semi || strictness == JoinStrictness::Anti) && (kind != JoinKind::Left && kind != JoinKind::Right))
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, " SEMI|ANTI JOIN should be LEFT or RIGHT");
|
||||
|
||||
if (kind == JoinKind::Comma)
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Second parameter of storage Join must be LEFT or INNER or RIGHT or FULL (without quotes).");
|
||||
|
||||
|
@ -1457,6 +1457,7 @@ bool StorageMergeTree::scheduleDataProcessingJob(BackgroundJobsAssignee & assign
|
||||
cleared_count += clearOldPartsFromFilesystem();
|
||||
cleared_count += clearOldMutations();
|
||||
cleared_count += clearEmptyParts();
|
||||
cleared_count += unloadPrimaryKeysOfOutdatedParts();
|
||||
return cleared_count;
|
||||
/// TODO maybe take into account number of cleared objects when calculating backoff
|
||||
}, common_assignee_trigger, getStorageID()), /* need_trigger */ false);
|
||||
|
@ -32,7 +32,6 @@ ColumnsDescription StorageSystemS3Queue::getColumnsDescription()
|
||||
{"status", std::make_shared<DataTypeString>(), "Status of processing: Processed, Processing, Failed"},
|
||||
{"processing_start_time", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeDateTime>()), "Time at which processing of the file started"},
|
||||
{"processing_end_time", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeDateTime>()), "Time at which processing of the file ended"},
|
||||
{"ProfileEvents", std::make_shared<DataTypeMap>(std::make_shared<DataTypeString>(), std::make_shared<DataTypeUInt64>()), "Profile events collected during processing of the file"},
|
||||
{"exception", std::make_shared<DataTypeString>(), "Exception which happened during processing"},
|
||||
};
|
||||
}
|
||||
@ -65,8 +64,6 @@ void StorageSystemS3Queue::fillData(MutableColumns & res_columns, ContextPtr, co
|
||||
else
|
||||
res_columns[i++]->insertDefault();
|
||||
|
||||
ProfileEvents::dumpToMapColumn(file_status->profile_counters.getPartiallyAtomicSnapshot(), res_columns[i++].get(), true);
|
||||
|
||||
res_columns[i++]->insert(file_status->getException());
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <Poco/JSON/JSON.h>
|
||||
#include <Poco/JSON/Object.h>
|
||||
#include <Poco/JSON/Stringifier.h>
|
||||
#include <Poco/JSONString.h>
|
||||
#include "base/types.h"
|
||||
#include <Access/Common/SSLCertificateSubjects.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
@ -142,10 +145,19 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, ContextPtr conte
|
||||
}
|
||||
else if (auth_data.getType() == AuthenticationType::SSL_CERTIFICATE)
|
||||
{
|
||||
Poco::JSON::Array::Ptr arr = new Poco::JSON::Array();
|
||||
for (const auto & common_name : auth_data.getSSLCertificateCommonNames())
|
||||
arr->add(common_name);
|
||||
auth_params_json.set("common_names", arr);
|
||||
Poco::JSON::Array::Ptr common_names = new Poco::JSON::Array();
|
||||
Poco::JSON::Array::Ptr subject_alt_names = new Poco::JSON::Array();
|
||||
|
||||
const auto & subjects = auth_data.getSSLCertificateSubjects();
|
||||
for (const String & subject : subjects.at(SSLCertificateSubjects::Type::CN))
|
||||
common_names->add(subject);
|
||||
for (const String & subject : subjects.at(SSLCertificateSubjects::Type::SAN))
|
||||
subject_alt_names->add(subject);
|
||||
|
||||
if (common_names->size() > 0)
|
||||
auth_params_json.set("common_names", common_names);
|
||||
if (subject_alt_names->size() > 0)
|
||||
auth_params_json.set("subject_alt_names", subject_alt_names);
|
||||
}
|
||||
|
||||
std::ostringstream oss; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
|
||||
|
@ -36,7 +36,7 @@ StoragePtr ITableFunction::execute(const ASTPtr & ast_function, ContextPtr conte
|
||||
if (cached_columns.empty())
|
||||
return executeImpl(ast_function, context, table_name, std::move(cached_columns), is_insert_query);
|
||||
|
||||
if (hasStaticStructure() && cached_columns == getActualTableStructure(context,is_insert_query))
|
||||
if (hasStaticStructure() && cached_columns == getActualTableStructure(context, is_insert_query))
|
||||
return executeImpl(ast_function, context_to_use, table_name, std::move(cached_columns), is_insert_query);
|
||||
|
||||
auto this_table_function = shared_from_this();
|
||||
|
@ -293,6 +293,16 @@ def test_cmd_conf(started_cluster):
|
||||
assert result["configuration_change_tries_count"] == "20"
|
||||
|
||||
assert result["async_replication"] == "true"
|
||||
|
||||
assert result["latest_logs_cache_size_threshold"] == "1073741824"
|
||||
assert result["commit_logs_cache_size_threshold"] == "524288000"
|
||||
|
||||
assert result["disk_move_retries_wait_ms"] == "1000"
|
||||
assert result["disk_move_retries_during_init"] == "100"
|
||||
|
||||
assert result["log_slow_total_threshold_ms"] == "5000"
|
||||
assert result["log_slow_cpu_threshold_ms"] == "100"
|
||||
assert result["log_slow_connection_operation_threshold_ms"] == "1000"
|
||||
finally:
|
||||
close_keeper_socket(client)
|
||||
|
||||
|
@ -40,6 +40,16 @@ create_table_sql_template = """
|
||||
PRIMARY KEY (`id`)) ENGINE=InnoDB;
|
||||
"""
|
||||
|
||||
create_table_sql_nullable_template = """
|
||||
CREATE TABLE `clickhouse`.`{}` (
|
||||
`id` integer not null,
|
||||
`col1` integer,
|
||||
`col2` decimal(15,10),
|
||||
`col3` varchar(32),
|
||||
`col4` datetime
|
||||
)
|
||||
"""
|
||||
|
||||
|
||||
def skip_test_msan(instance):
|
||||
if instance.is_built_with_memory_sanitizer():
|
||||
@ -77,6 +87,11 @@ def create_mysql_db(conn, name):
|
||||
cursor.execute("CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(name))
|
||||
|
||||
|
||||
def create_mysql_nullable_table(conn, table_name):
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(create_table_sql_nullable_template.format(table_name))
|
||||
|
||||
|
||||
def create_mysql_table(conn, table_name):
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(create_table_sql_template.format(table_name))
|
||||
@ -192,6 +207,46 @@ def started_cluster():
|
||||
cluster.shutdown()
|
||||
|
||||
|
||||
def test_mysql_odbc_select_nullable(started_cluster):
|
||||
skip_test_msan(node1)
|
||||
mysql_setup = node1.odbc_drivers["MySQL"]
|
||||
|
||||
table_name = "test_insert_nullable_select"
|
||||
conn = get_mysql_conn()
|
||||
create_mysql_nullable_table(conn, table_name)
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"INSERT INTO clickhouse.{} VALUES(1, 1, 1.23456, 'data1', '2010-01-01 00:00:00');".format(
|
||||
table_name
|
||||
)
|
||||
)
|
||||
cursor.execute(
|
||||
"INSERT INTO clickhouse.{} VALUES(2, NULL, NULL, NULL, NULL);".format(
|
||||
table_name
|
||||
)
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
node1.query(
|
||||
"""
|
||||
CREATE TABLE {}(id UInt32, col1 Nullable(UInt32), col2 Nullable(Decimal(15, 10)), col3 Nullable(String), col4 Nullable(DateTime)) ENGINE = ODBC('DSN={}', 'clickhouse', '{}');
|
||||
""".format(
|
||||
table_name, mysql_setup["DSN"], table_name
|
||||
)
|
||||
)
|
||||
|
||||
assert (
|
||||
node1.query(
|
||||
"SELECT id, col1, col2, col3, col4 from {} order by id asc".format(
|
||||
table_name
|
||||
)
|
||||
)
|
||||
== "1\t1\t1.23456\tdata1\t2010-01-01 00:00:00\n2\t\\N\t\\N\t\\N\t\\N\n"
|
||||
)
|
||||
drop_mysql_table(conn, table_name)
|
||||
conn.close()
|
||||
|
||||
|
||||
def test_mysql_simple_select_works(started_cluster):
|
||||
skip_test_msan(node1)
|
||||
|
||||
|
@ -1,32 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
wCCDUCIbtJgxTrUk1Kgty5ipLgP64m29Pw==
|
||||
CQYDVQQDDAJjYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALHzp+SR
|
||||
T8EtrMBYNlgwIUGMZaXomQPwsjOpjt3RUsdE3LCQ15rLuyBwZ0SbLMDOazCDA7Xr
|
||||
+AXHDYwg/PCJhe2N4NTzfgnWqbkIGwYLhys95Xxq+q+kV7Csk/27JSk1rsK3Nru/
|
||||
Iuj/NWgBkAQC8n10qfbJSXHcXm9wDVy/L8t7DXwxkX70LToGWsb6QW6VkiWe/QOW
|
||||
QYTMVncqjrtLTCTnqGIk0s6ZIifgPLfaYJxtwK+LdIoJioSbAuVfHmVTe10vjonO
|
||||
YqJ56KfqOn/G7dIf1l9gOLFBAe4jUf3RS1wkQMdk+oEGLbGnShgW+BQMfB48RkrQ
|
||||
486h7slzwC29jBJLRARI2Oc9p8/zBDVph0pxkjVGka8dfIkZbmTD932h/1gfMgQl
|
||||
F20G/H5FF1jk37bDcsczns0c24S1F2uJbzOlHjFLhqmH1IaVCWsYawfBs9khModW
|
||||
VS6+WAv//cqWE3KmmJ2EdtAmzMCJzAQUEyrMZWmrFrBzpACyMq2zFEtyIXsCXpgq
|
||||
eW4odxIIZlClibo1FGrflqN+hXnAhRyCj7WJBQ0ZPrEdRMRpBYhYdmygPJ+lWfsg
|
||||
HOtNnshSuJTXGJTtsuJVr4Ioeq6tKfWGofRu4vvT6cILZjbp9VaxxfVLS7bTsjWR
|
||||
c+5xHp+KbcjSfw2cJHQN85hlWTpMe9jPhgt/AgMBAAGjUzBRMB0GA1UdDgQWBBSJ
|
||||
Kj1dSYN0jW+Mu0xFQrobZFmQpTAfBgNVHSMEGDAWgBSJKj1dSYN0jW+Mu0xFQrob
|
||||
ZFmQpTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCEm/epjNWe
|
||||
w0A+1M3i0y8adrXWdTeRXuP3Klgtjh3NGFKNm9WGnOAufsqUIpVwKLw1uYNIhiEA
|
||||
fj5KuD7YIVU9CrWx4Z/+lILUZhyn/br5mACtRiRTF/75/QwLcDz5z7K9MyMzdL99
|
||||
DLQ9bd3JCuEgVj6zacPrALwWVhM8u9fNGJxdQANnIC8yTY5+ZE59/fn7UI787JuR
|
||||
4njOGWSVnDavbTyJCPMPiUkgwqL+QSWBcNbGAPzMaAblvc1SL2Lj/ikFDAETAZs2
|
||||
T/3ZqBqHEOuVhFQYTAvMAdMQX3w8bYv/CGL8++W+qHazY+uqPypd9CLnICbnkZmr
|
||||
P+id9WleGl2F//u1CQ+YA2Q3EazSFhwRLA7IKIVCrYVaBsbe/bpxxZb6+AQVfM/i
|
||||
+7+fCbr7A5HDe9Fi4dClv6xPI0GZZkarhQPsoLPaDQeqM4OE+K6oPSHJnqfAB8v3
|
||||
NgTt1QuVnKhwveX5DDEP4t/Qt4j2n7AFpeoZDEA8aM33K0noXNrwqHz3991O1RWz
|
||||
t/gd+cFG/Z1jRP8kYtfAV8go2nzt8QvqBhfIcNnMwD8cwuKJ5G7SdqLvDFj3XCCO
|
||||
YqQAALl4QFs046eVDEWLajSESmj4fCaTmO05sHHLy7U5asoAo/MWGbmGmL+8ExUX
|
||||
sPO9r12lPJ7IThJ13PSqbJIJnnloL/XCxA==
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -1 +1 @@
|
||||
05F10C67567FE30795D77AF2540F6AC8D4CF2461
|
||||
05F10C67567FE30795D77AF2540F6AC8D4CF2470
|
||||
|
@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
7MqACWG/2mFExJnaXtgA2HS8NYPKUcQ=
|
||||
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
|
||||
MJuwAZJiZb+dQc0uwMkAEPMEfOQ1BI1+
|
||||
-----END PRIVATE KEY-----
|
||||
|
@ -1,30 +1,30 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDBh20QUvlucIAd
|
||||
Db+ujg8QfJVNcQo/+Ipi2T2XC8z3bS9H0dU0vhvCoxkq8c5xKYeDW5xUe3BOnyrb
|
||||
gvzkklDHAXkYl2cY1tfrmIxqehxiWLsmnlSjK4T9luwQ/RrjLtZdJOvuikfIBglv
|
||||
tPUTh/FMuq7wiPmhpeqYMGmys2FiLtOBICLHQoI/WkaZMsaE8BXa4gyZ4G07rV6z
|
||||
wgvi2qM2CQQ+LZ8Ac0n6TJT/taxD3PzKbeG3g8iwPb6deblWEDWiSqKb7gqH5aix
|
||||
NOEIXDHbm7FI0EopLrc+cf3IRJclhvMP+ZIwCmZncCS2v8sYNzbAqD3Zko+GlcEM
|
||||
CtLHmOaOslKXQA3NFtgc0PL3rkKEl/61rH/5VkHtlRu2hJ/OE0iaFFsIFyyEULhX
|
||||
coxNd8NFXaayaOmdO2LrqN3CfXZ55ofyzmS/OLSwuKOKkrJ2+VI40ux1giA1bbL8
|
||||
+tbSsgKSWdSL7KxLIY+tNsIayA0wmeozIaQS6WSI/BkcUkSsaQvjaruWabKLwjVm
|
||||
6WAJAZ7O7L8BGWkXymNUpum24HGZNVWjClCDx6lI53VZCo2e0nqbVwn9ir9fMRGl
|
||||
wy3q4PfSIUc1JTb7/zCqxtWPbpDtsW+1AbxT85Hoi9PTB00dW2XL6MIkjtyJQbwo
|
||||
sY7h7q+VLbBl+MLM6Uq4bWgmKmRt+wIDAQABAoICAF9pe5lFNyk+OMNaMGsIKaAo
|
||||
s9kyxmlkiSGT1fweesZvo5RGfNVcdsY+b92OyodbAK7/3vJ9yxBQA6qmiTTNeBqs
|
||||
/L1lg5Qo89n44x1pp43LDjXLcJHjllUJ78euaW+g+1l/pvv7W8lfRI64yez/pDT+
|
||||
gtoexefuq1qt36aVLolf6bGrHMpdXWaLhOvprxsCXNwFf03r6h62ak64d/C3dyjg
|
||||
SCG5jz8DF/FZiUoKkOwCSvUoOFSoGazePBhaV0f5hN/G6SV0NefrD4CSP/HFtmT9
|
||||
fOmXm0Bzgi88tvBh9JyxTCtPkUWzEuqjTM52f1QogIt6Rsf6LF2ffkYIHgP+u4e5
|
||||
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
|
||||
3UTpTl6z0FqLEeB20OY2dIyoPhdNoA==
|
||||
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
|
||||
NMnXQHpKE2RaT22UJ6z3W+biQqNlhlVW
|
||||
-----END PRIVATE KEY-----
|
||||
|
@ -1,27 +1,27 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
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
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
@ -1,30 +1,30 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
PK2zQzz0JkpsDD7mGM+S6apZHiLgHg==
|
||||
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDVIAS4GRI4lty5
|
||||
oxpQrte4dhEWHO+WF/u3rG8P4jFjK3K137zTbrSeB+4TrFfNWaTBEKLh0X6IPCJ6
|
||||
2igrsJm9vAy4SWSZaROPYWcXlCcLOMjfFQgk4K/7S7U7L7EkvkxgOfAdvRx2oJSc
|
||||
GNMNpjpTlXFMTpI53uFR6JCzqJoc86nKkywo8FLJWakZ/kg4F8kcPT+a3if5uhN+
|
||||
nRcgXlYJWb3mpVaeLiv006lVRSWAZYw9tjPcKznqPQCL667uVZYAzR7vq8KoEnhP
|
||||
2xnMIV9ifSfvpcDsbBQ0eziC2N98qA+/+jTetUiRKEYe8WU0JK/w3Nx6b42Mo+GG
|
||||
oHViqtsQ2cyMR/kHxDELLLhb7pauS++kyaVwd3HsgrtjRL2/+et6dRL10G6eWY8+
|
||||
zo6NXpaG7PXqb32wpogDZk8RvBiyrXi1343KYePdoHSMNJ7Fff2yMxOQu5Z33+Jx
|
||||
FPRP7hCc9BU8OtVY3GT7aahMyxP/GmwVOPKU4+R6iqPDbI8fYT5erazuIfNcjGqs
|
||||
G0A5s2tSrFPgjyBYsnMr/B5+MOiRI8J1HNPKzqEN3ux46izaZ/F+kYq1UFK8ElOy
|
||||
/EUynjgjgS4OgDF3x/36z0ZzUI1Bv2e7QU40yYZt/KrnMchyNyeY8F+r5/4wX3RR
|
||||
30+uddFdEPX84M6dx938h6Zy1tasQwIDAQABAoICAQDIuNYY+OvTRipt37IaCQF8
|
||||
Zh4jgG8ZIk9dJlaXVAYFi1cG+chiLSKIr5lHCArNiT8E4gE1wtNzxYcHw00QEMxL
|
||||
CL/GFMFdRrw4TpkEePDovbtZdvprmP3FJAF00673lw5hlk+SApi7FPPBrBOiCEto
|
||||
ixfgsSNAw6vcM7eMrR8wY0AnXMK7b9PYdMwxge5MfgJXyUuNNOvbY6eWmKa+Qnqv
|
||||
ZcjXYCKa6YtWkr4pY+005u7U9DQViNSLypYoMXlYWFzlNkqLmW3EU1jihMzgFxI5
|
||||
tPwW1TpEsGm7H84SVeTuB26F9UUz9vJ4W8DmxZz2JhNaOvifi056BaKS466KlbWo
|
||||
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
|
||||
Xe2nzT23gDTuPny4yivLAMHPZPfGLLg4
|
||||
-----END PRIVATE KEY-----
|
||||
|
@ -1,27 +1,27 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIEnDCCAoQCAQAwVzELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUtU3RhdGUx
|
||||
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEQMA4GA1UEAwwHY2xp
|
||||
ZW50MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPpDQjGPdPUiGXyb
|
||||
mTEEbneSxXDaz/+2H4Dl9QLq3NnqozavqqZksseYsvOwLbzdZ92sRLHf5B1Wwo2h
|
||||
3SbOGtb6CD3NMqV5P/nvHghn3KD60l5Jy81W8aJ+pwra8tVf/O0oDcJ2qwHABhMY
|
||||
m7cf7vk3Llt4clQ2g9wj6o4UuCFjGXDqPLxO+xN2Qtx9YZdxUGTrUtwwFgaoJiUq
|
||||
oeuagMtJ2OlmTsRM8VNnddLqEnqTWNtV3hloH709fA4RzudCOhHDwx2p+zKDwDTn
|
||||
OFgOVaX0I76CZ/eZ3qU4cwIZ5bJaJjowi0XCP0Pk3LYQ+wPrDsIuP1tdxVAlU0rX
|
||||
XePxi0yrwDLzTi8PPogwkMSkfSRf4xlgQRlnQjdya4A6h7VTvh92tpMDi6EP1JA1
|
||||
nTNebOf5AjKwNHQ6B5XuTRP0PEUIDAfV9mNriR5vnn+oM44AM7FQ+tFwJbc8CQX6
|
||||
487M9KGsHmVsf60fWCBmgZicof0XSpVrnMDJdGARzgmxz4z/Eunrr9uup0SttZdW
|
||||
ns1lLwWpbnrCk7I3F4SZ8On3Yf+RxFLZvBJjvHKfRopi81YkralkKfu+Se6TE0Qp
|
||||
kPEEaXW5zqvVkt1gW9j79zeBZRFzjuT35F5m7fWi6e7V/W2crtw4lGxH/LYX397Z
|
||||
P7i7cT6N+g4JYkeLgMy18S1jiZtHAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||
h9/gIGo83p/F0NDDWGr4P9LxdrE+kkaZF2BxRv2rkty/OC1Qe2lcJPWaEOQY07an
|
||||
witmxGPaZB6e764J9z/C2l8hoh9LFAIZ+gPBzMEqPBO2/5WYWjjPzzUlkTBczIdo
|
||||
mCZywvYMrdPQ/F2LnZd8iQO0pmFUGC92vV9Hb/i3y7RthnJWRYv+2F/D5ZWE07sz
|
||||
xA0gwmnY8d8/G+O2CwgGsHLl2tByfnePDqq+ogwRKXtsPeJwWloFvnPRHE0OmkHf
|
||||
n2XHbbLMS/m8Wi5utN/LpMV+WITQHMxGPGXcX6XOWVFQuesfI7DKoqZzk/aB2IFO
|
||||
tu2deFdfnrj3Md8PRAQBe0Ufig0gl6EvutdmiNCeiDloPwV4gLvH7SLQmLheOPP2
|
||||
CQZh1skRxhPmnJYD4rrsMGv86dlhEvtnxCO+cUrxnUAAr81BAX/Fo1Img0rPaanD
|
||||
N4/FG7LnU/Rk8g9roN/8v8s62CnyxcQ4UAvSWAaRrudpErDk+L24Ib4UCtcYiGSB
|
||||
Dj2tK5SMfcXn+bR2HTdVIKHWHIK1X6bS7Jn9ZXlDg/MCyCILeOmW523FoLfTvNVH
|
||||
IY9MgNe5KDX7dpPCAJFWwmidekNz+sSbpu6Br8IgWd6SuTEx8Lmb9GB0V7P2CHlE
|
||||
1ASW5YJMgVPJLQ9LQhRIim2+pL3Pz/SM+oijeSyEoSw=
|
||||
ZW50MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANUgBLgZEjiW3Lmj
|
||||
GlCu17h2ERYc75YX+7esbw/iMWMrcrXfvNNutJ4H7hOsV81ZpMEQouHRfog8Inra
|
||||
KCuwmb28DLhJZJlpE49hZxeUJws4yN8VCCTgr/tLtTsvsSS+TGA58B29HHaglJwY
|
||||
0w2mOlOVcUxOkjne4VHokLOomhzzqcqTLCjwUslZqRn+SDgXyRw9P5reJ/m6E36d
|
||||
FyBeVglZvealVp4uK/TTqVVFJYBljD22M9wrOeo9AIvrru5VlgDNHu+rwqgSeE/b
|
||||
GcwhX2J9J++lwOxsFDR7OILY33yoD7/6NN61SJEoRh7xZTQkr/Dc3HpvjYyj4Yag
|
||||
dWKq2xDZzIxH+QfEMQssuFvulq5L76TJpXB3ceyCu2NEvb/563p1EvXQbp5Zjz7O
|
||||
jo1elobs9epvfbCmiANmTxG8GLKteLXfjcph492gdIw0nsV9/bIzE5C7lnff4nEU
|
||||
9E/uEJz0FTw61VjcZPtpqEzLE/8abBU48pTj5HqKo8Nsjx9hPl6trO4h81yMaqwb
|
||||
QDmza1KsU+CPIFiycyv8Hn4w6JEjwnUc08rOoQ3e7HjqLNpn8X6RirVQUrwSU7L8
|
||||
RTKeOCOBLg6AMXfH/frPRnNQjUG/Z7tBTjTJhm38qucxyHI3J5jwX6vn/jBfdFHf
|
||||
T6510V0Q9fzgzp3H3fyHpnLW1qxDAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||
dr0LKtpOa+Xu9PKwnlsM48/ltph4q9+tsu4CeC8XGoLFNbVIALuZZsKZDehTf+/d
|
||||
bgEtjW8vVnBGAvVodo1MgCHnhPPensDLfyggAULT2X400cly+suGbKeu3kIOlKCs
|
||||
TQsFdNKOPm17NcpuM1wTik2UT2EWLdzZ25Wy3Coid+ILrf5YZ75djqtxZlYbRiw4
|
||||
4IndIjN0bYsn8l6Z8Pt5HdJ1nQnbDZhQrx6FXWZ3eSSmpklfl4O07z0KlXi1Nmaf
|
||||
OiVcOMvZUnM8pYmNvul8Jus/XmP8x3jSbYzJDNOJ3YV8+OD8DVG3pLM8U1FmjCZ7
|
||||
KiR5DNSxZFpHGXhUqDpTrhLgoqGK9chOqPdzU7Mp4taEO9FV8Goc7BCeOKB3Znxb
|
||||
XDIszs0oBIHO/tsqUwEcWBI0vjyC2pBYQAYK++qwwmvbfWg5lrb7eH1ZO42DU9QD
|
||||
AVR/5luxImAA11AmSsGf8i+FJ3F63PzSr0uUG7BnTLC03xna7dPdKXS/pGojNVBT
|
||||
Q5A5J0rB3+4L2mZLE3mjst3t1xHfLW/0RVRqGwz0QUIloZkO6wPN6Jz6l5Q+TgCY
|
||||
uEks1YN/qlwjHwI3ycT+Hr/sY5igT0OAySo7qa7lN13qTiO2z7eAMDgafNnq34kJ
|
||||
4OQDCE28Bni0fFRIaqVCqTU31Kei5jbORif2wK81Zmw=
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
@ -1,30 +1,30 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
7tLJO1z1/eDbntbQC4cvewqNRYhwlnWe
|
||||
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
|
||||
KB6GTGRi7uqGHYScU6+wRMHjdVzdKGNM
|
||||
-----END PRIVATE KEY-----
|
||||
|
@ -1,27 +1,27 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
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
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user