mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
Merge remote-tracking branch 'upstream/master' into DateTime64
This commit is contained in:
commit
c6eb0fcff7
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -1,3 +1,4 @@
|
||||
dbms/* @ClickHouse/core-assigner
|
||||
utils/* @ClickHouse/core-assigner
|
||||
docs/* @ClickHouse/docs
|
||||
docs/zh/* @ClickHouse/docs-zh
|
||||
|
1
.github/labeler.keywords.yml
vendored
1
.github/labeler.keywords.yml
vendored
@ -1 +0,0 @@
|
||||
pr-feature: "New Feature"
|
19
.github/labeler.yml
vendored
19
.github/labeler.yml
vendored
@ -1,19 +0,0 @@
|
||||
# Documentation PRs
|
||||
documentation:
|
||||
- "**/*.md"
|
||||
- "docs/**/*"
|
||||
pr-documentation:
|
||||
- "**/*.md"
|
||||
- "docs/**/*"
|
||||
|
||||
# Component labels
|
||||
comp-mutations:
|
||||
- "**/*Mutation*"
|
||||
comp-matview:
|
||||
- "**/*MaterializedView*"
|
||||
comp-skipidx:
|
||||
- "**/*Indices*"
|
||||
comp-kafka:
|
||||
- "dbms/src/Storages/Kafka/**/*"
|
||||
- "dbms/tests/integration/test_storage_kafka/**/*"
|
||||
- "utils/kafka/**/*"
|
67
.github/stale.yml
vendored
67
.github/stale.yml
vendored
@ -1,67 +0,0 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 45
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 30
|
||||
|
||||
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
|
||||
onlyLabels: []
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- bug
|
||||
- feature
|
||||
- memory
|
||||
- performance
|
||||
- prio-crit
|
||||
- prio-major
|
||||
- st-accepted
|
||||
- st-in-progress
|
||||
- st-waiting-for-fix
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false)
|
||||
exemptAssignees: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
# closeComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
pulls:
|
||||
daysUntilStale: 365
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had
|
||||
any activity for over a year. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
11
.github/workflows/labeler.yml
vendored
11
.github/workflows/labeler.yml
vendored
@ -1,11 +0,0 @@
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
pull_request
|
||||
|
||||
jobs:
|
||||
by-filename:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: "actions/labeler@v2"
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -245,3 +245,6 @@ website/package-lock.json
|
||||
/.ccls-cache
|
||||
|
||||
/compile_commands.json
|
||||
|
||||
# Toolchains
|
||||
/cmake/toolchain/*
|
||||
|
257
CHANGELOG.md
257
CHANGELOG.md
@ -1,3 +1,253 @@
|
||||
## ClickHouse release v19.16.2.2, 30-10-2019
|
||||
|
||||
### Backward Incompatible Change
|
||||
* Add missing arity validation for count/counIf.
|
||||
[#7095](https://github.com/ClickHouse/ClickHouse/issues/7095)
|
||||
[#7298](https://github.com/ClickHouse/ClickHouse/pull/7298) ([Vdimir](https://github.com/Vdimir))
|
||||
* Remove legacy `asterisk_left_columns_only` setting (it was disabled by default).
|
||||
[#7335](https://github.com/ClickHouse/ClickHouse/pull/7335) ([Artem
|
||||
Zuikov](https://github.com/4ertus2))
|
||||
* Format strings for Template data format are now specified in files.
|
||||
[#7118](https://github.com/ClickHouse/ClickHouse/pull/7118)
|
||||
([tavplubix](https://github.com/tavplubix))
|
||||
|
||||
### New Feature
|
||||
* Introduce uniqCombined64() to calculate cardinality greater than UINT_MAX.
|
||||
[#7213](https://github.com/ClickHouse/ClickHouse/pull/7213),
|
||||
[#7222](https://github.com/ClickHouse/ClickHouse/pull/7222) ([Azat
|
||||
Khuzhin](https://github.com/azat))
|
||||
* Support Bloom filter indexes on Array columns.
|
||||
[#6984](https://github.com/ClickHouse/ClickHouse/pull/6984)
|
||||
([achimbab](https://github.com/achimbab))
|
||||
* Add a function `getMacro(name)` that returns String with the value of corresponding `<macros>`
|
||||
from server configuration. [#7240](https://github.com/ClickHouse/ClickHouse/pull/7240)
|
||||
([alexey-milovidov](https://github.com/alexey-milovidov))
|
||||
* Set two configuration options for a dictionary based on an HTTP source: `credentials` and
|
||||
`http-headers`. [#7092](https://github.com/ClickHouse/ClickHouse/pull/7092) ([Guillaume
|
||||
Tassery](https://github.com/YiuRULE))
|
||||
* Add a new ProfileEvent `Merge` that counts the number of launched background merges.
|
||||
[#7093](https://github.com/ClickHouse/ClickHouse/pull/7093) ([Mikhail
|
||||
Korotov](https://github.com/millb))
|
||||
* Add fullHostName function that returns a fully qualified domain name.
|
||||
[#7263](https://github.com/ClickHouse/ClickHouse/issues/7263)
|
||||
[#7291](https://github.com/ClickHouse/ClickHouse/pull/7291) ([sundyli](https://github.com/sundy-li))
|
||||
* Add function `arraySplit` and `arrayReverseSplit` which split an array by "cut off"
|
||||
conditions. They are useful in time sequence handling.
|
||||
[#7294](https://github.com/ClickHouse/ClickHouse/pull/7294) ([hcz](https://github.com/hczhcz))
|
||||
* Add new functions that return the Array of all matched indices in multiMatch family of functions.
|
||||
[#7299](https://github.com/ClickHouse/ClickHouse/pull/7299) ([Danila
|
||||
Kutenin](https://github.com/danlark1))
|
||||
* Add a new database engine `Lazy` that is optimized for storing a large number of small -Log
|
||||
tables. [#7171](https://github.com/ClickHouse/ClickHouse/pull/7171) ([Nikita
|
||||
Vasilev](https://github.com/nikvas0))
|
||||
* Add aggregate functions groupBitmapAnd, -Or, -Xor for bitmap columns. [#7109](https://github.com/ClickHouse/ClickHouse/pull/7109) ([Zhichang
|
||||
Yu](https://github.com/yuzhichang))
|
||||
* Add aggregate function combinators -OrNull and -OrDefault, which return null
|
||||
or default values when there is nothing to aggregate.
|
||||
[#7331](https://github.com/ClickHouse/ClickHouse/pull/7331)
|
||||
([hcz](https://github.com/hczhcz))
|
||||
* Introduce CustomSeparated data format that supports custom escaping and
|
||||
delimiter rules. [#7118](https://github.com/ClickHouse/ClickHouse/pull/7118)
|
||||
([tavplubix](https://github.com/tavplubix))
|
||||
|
||||
### Bug Fix
|
||||
* Fix wrong query result if it has `WHERE IN (SELECT ...)` section and `optimize_read_in_order` is
|
||||
used. [#7371](https://github.com/ClickHouse/ClickHouse/pull/7371) ([Anton
|
||||
Popov](https://github.com/CurtizJ))
|
||||
* Disabled MariaDB authentication plugin, which depends on files outside of project.
|
||||
[#7140](https://github.com/ClickHouse/ClickHouse/pull/7140) ([Yuriy
|
||||
Baranov](https://github.com/yurriy))
|
||||
* Fix exception `Cannot convert column ... because it is constant but values of constants are
|
||||
different in source and result` which could rarely happen when functions `now()`, `today()`,
|
||||
`yesterday()`, `randConstant()` are used.
|
||||
[#7156](https://github.com/ClickHouse/ClickHouse/pull/7156) ([Nikolai
|
||||
Kochetov](https://github.com/KochetovNicolai))
|
||||
* Fixed issue of using HTTP keep alive timeout instead of TCP keep alive timeout.
|
||||
[#7351](https://github.com/ClickHouse/ClickHouse/pull/7351) ([Vasily
|
||||
Nemkov](https://github.com/Enmk))
|
||||
* Fixed a segmentation fault in groupBitmapOr (issue [#7109](https://github.com/ClickHouse/ClickHouse/issues/7109)).
|
||||
[#7289](https://github.com/ClickHouse/ClickHouse/pull/7289) ([Zhichang
|
||||
Yu](https://github.com/yuzhichang))
|
||||
* For materialized views the commit for Kafka is called after all data were written.
|
||||
[#7175](https://github.com/ClickHouse/ClickHouse/pull/7175) ([Ivan](https://github.com/abyss7))
|
||||
* Fixed wrong `duration_ms` value in `system.part_log` table. It was ten times off.
|
||||
[#7172](https://github.com/ClickHouse/ClickHouse/pull/7172) ([Vladimir
|
||||
Chebotarev](https://github.com/excitoon))
|
||||
* A quick fix to resolve crash in LIVE VIEW table and re-enabling all LIVE VIEW tests.
|
||||
[#7201](https://github.com/ClickHouse/ClickHouse/pull/7201)
|
||||
([vzakaznikov](https://github.com/vzakaznikov))
|
||||
* Serialize NULL values correctly in min/max indexes of MergeTree parts.
|
||||
[#7234](https://github.com/ClickHouse/ClickHouse/pull/7234) ([Alexander
|
||||
Kuzmenkov](https://github.com/akuzm))
|
||||
* Don't put virtual columns to .sql metadata when table is created as `CREATE TABLE AS`.
|
||||
[#7183](https://github.com/ClickHouse/ClickHouse/pull/7183) ([Ivan](https://github.com/abyss7))
|
||||
* Fix segmentation fault in `ATTACH PART` query.
|
||||
[#7185](https://github.com/ClickHouse/ClickHouse/pull/7185)
|
||||
([alesapin](https://github.com/alesapin))
|
||||
* Fix wrong result for some queries given by the optimization of empty IN subqueries and empty
|
||||
INNER/RIGHT JOIN. [#7284](https://github.com/ClickHouse/ClickHouse/pull/7284) ([Nikolai
|
||||
Kochetov](https://github.com/KochetovNicolai))
|
||||
* Fixing AddressSanitizer error in the LIVE VIEW getHeader() method.
|
||||
[#7271](https://github.com/ClickHouse/ClickHouse/pull/7271)
|
||||
([vzakaznikov](https://github.com/vzakaznikov))
|
||||
|
||||
### Improvement
|
||||
* Add a message in case of queue_wait_max_ms wait takes place.
|
||||
[#7390](https://github.com/ClickHouse/ClickHouse/pull/7390) ([Azat
|
||||
Khuzhin](https://github.com/azat))
|
||||
* Made setting `s3_min_upload_part_size` table-level.
|
||||
[#7059](https://github.com/ClickHouse/ClickHouse/pull/7059) ([Vladimir
|
||||
Chebotarev](https://github.com/excitoon))
|
||||
* Check TTL in StorageFactory. [#7304](https://github.com/ClickHouse/ClickHouse/pull/7304)
|
||||
([sundyli](https://github.com/sundy-li))
|
||||
* Squash left-hand blocks in partial merge join (optimization).
|
||||
[#7122](https://github.com/ClickHouse/ClickHouse/pull/7122) ([Artem
|
||||
Zuikov](https://github.com/4ertus2))
|
||||
* Do not allow non-deterministic functions in mutations of Replicated table engines, because this
|
||||
can introduce inconsistencies between replicas.
|
||||
[#7247](https://github.com/ClickHouse/ClickHouse/pull/7247) ([Alexander
|
||||
Kazakov](https://github.com/Akazz))
|
||||
* Disable memory tracker while converting exception stack trace to string. It can prevent the loss
|
||||
of error messages of type `Memory limit exceeded` on server, which caused the `Attempt to read
|
||||
after eof` exception on client. [#7264](https://github.com/ClickHouse/ClickHouse/pull/7264)
|
||||
([Nikolai Kochetov](https://github.com/KochetovNicolai))
|
||||
* Miscellaneous format improvements. Resolves
|
||||
[#6033](https://github.com/ClickHouse/ClickHouse/issues/6033),
|
||||
[#2633](https://github.com/ClickHouse/ClickHouse/issues/2633),
|
||||
[#6611](https://github.com/ClickHouse/ClickHouse/issues/6611),
|
||||
[#6742](https://github.com/ClickHouse/ClickHouse/issues/6742)
|
||||
[#7215](https://github.com/ClickHouse/ClickHouse/pull/7215)
|
||||
([tavplubix](https://github.com/tavplubix))
|
||||
* ClickHouse ignores values on the right side of IN operator that are not convertible to the left
|
||||
side type. Make it work properly for compound types -- Array and Tuple.
|
||||
[#7283](https://github.com/ClickHouse/ClickHouse/pull/7283) ([Alexander
|
||||
Kuzmenkov](https://github.com/akuzm))
|
||||
* Support missing inequalities for ASOF JOIN. It's possible to join less-or-equal variant and strict
|
||||
greater and less variants for ASOF column in ON syntax.
|
||||
[#7282](https://github.com/ClickHouse/ClickHouse/pull/7282) ([Artem
|
||||
Zuikov](https://github.com/4ertus2))
|
||||
* Optimize partial merge join. [#7070](https://github.com/ClickHouse/ClickHouse/pull/7070)
|
||||
([Artem Zuikov](https://github.com/4ertus2))
|
||||
* Do not use more then 98K of memory in uniqCombined functions.
|
||||
[#7236](https://github.com/ClickHouse/ClickHouse/pull/7236),
|
||||
[#7270](https://github.com/ClickHouse/ClickHouse/pull/7270) ([Azat
|
||||
Khuzhin](https://github.com/azat))
|
||||
* Flush parts of right-hand joining table on disk in PartialMergeJoin (if there is not enough
|
||||
memory). Load data back when needed. [#7186](https://github.com/ClickHouse/ClickHouse/pull/7186)
|
||||
([Artem Zuikov](https://github.com/4ertus2))
|
||||
|
||||
### Performance Improvement
|
||||
* Speed up joinGet with const arguments by avoiding data duplication.
|
||||
[#7359](https://github.com/ClickHouse/ClickHouse/pull/7359) ([Amos
|
||||
Bird](https://github.com/amosbird))
|
||||
* Return early if the subquery is empty.
|
||||
[#7007](https://github.com/ClickHouse/ClickHouse/pull/7007) ([小路](https://github.com/nicelulu))
|
||||
* Optimize parsing of SQL expression in Values.
|
||||
[#6781](https://github.com/ClickHouse/ClickHouse/pull/6781)
|
||||
([tavplubix](https://github.com/tavplubix))
|
||||
|
||||
### Build/Testing/Packaging Improvement
|
||||
* Disable some contribs for cross-compilation to Mac OS.
|
||||
[#7101](https://github.com/ClickHouse/ClickHouse/pull/7101) ([Ivan](https://github.com/abyss7))
|
||||
* Add missing linking with PocoXML for clickhouse_common_io.
|
||||
[#7200](https://github.com/ClickHouse/ClickHouse/pull/7200) ([Azat
|
||||
Khuzhin](https://github.com/azat))
|
||||
* Accept multiple test filter arguments in clickhouse-test.
|
||||
[#7226](https://github.com/ClickHouse/ClickHouse/pull/7226) ([Alexander
|
||||
Kuzmenkov](https://github.com/akuzm))
|
||||
* Enable musl and jemalloc for ARM. [#7300](https://github.com/ClickHouse/ClickHouse/pull/7300)
|
||||
([Amos Bird](https://github.com/amosbird))
|
||||
* Added `--client-option` parameter to `clickhouse-test` to pass additional parameters to client.
|
||||
[#7277](https://github.com/ClickHouse/ClickHouse/pull/7277) ([Nikolai
|
||||
Kochetov](https://github.com/KochetovNicolai))
|
||||
* Preserve existing configs on rpm package upgrade.
|
||||
[#7103](https://github.com/ClickHouse/ClickHouse/pull/7103)
|
||||
([filimonov](https://github.com/filimonov))
|
||||
* Fix errors detected by PVS. [#7153](https://github.com/ClickHouse/ClickHouse/pull/7153) ([Artem
|
||||
Zuikov](https://github.com/4ertus2))
|
||||
* Fix build for Darwin. [#7149](https://github.com/ClickHouse/ClickHouse/pull/7149)
|
||||
([Ivan](https://github.com/abyss7))
|
||||
* glibc 2.29 compatibility. [#7142](https://github.com/ClickHouse/ClickHouse/pull/7142) ([Amos
|
||||
Bird](https://github.com/amosbird))
|
||||
* Make sure dh_clean does not touch potential source files.
|
||||
[#7205](https://github.com/ClickHouse/ClickHouse/pull/7205) ([Amos
|
||||
Bird](https://github.com/amosbird))
|
||||
* Attempt to avoid conflict when updating from altinity rpm - it has config file packaged separately
|
||||
in clickhouse-server-common. [#7073](https://github.com/ClickHouse/ClickHouse/pull/7073)
|
||||
([filimonov](https://github.com/filimonov))
|
||||
* Optimize some header files for faster rebuilds.
|
||||
[#7212](https://github.com/ClickHouse/ClickHouse/pull/7212),
|
||||
[#7231](https://github.com/ClickHouse/ClickHouse/pull/7231) ([Alexander
|
||||
Kuzmenkov](https://github.com/akuzm))
|
||||
* Add performance tests for Date and DateTime. [#7332](https://github.com/ClickHouse/ClickHouse/pull/7332) ([Vasily
|
||||
Nemkov](https://github.com/Enmk))
|
||||
* Fix some tests that contained non-deterministic mutations.
|
||||
[#7132](https://github.com/ClickHouse/ClickHouse/pull/7132) ([Alexander
|
||||
Kazakov](https://github.com/Akazz))
|
||||
* Add build with MemorySanitizer to CI. [#7066](https://github.com/ClickHouse/ClickHouse/pull/7066)
|
||||
([Alexander Kuzmenkov](https://github.com/akuzm))
|
||||
* Avoid use of uninitialized values in MetricsTransmitter.
|
||||
[#7158](https://github.com/ClickHouse/ClickHouse/pull/7158) ([Azat
|
||||
Khuzhin](https://github.com/azat))
|
||||
* Fix some issues in Fields found by MemorySanitizer.
|
||||
[#7135](https://github.com/ClickHouse/ClickHouse/pull/7135),
|
||||
[#7179](https://github.com/ClickHouse/ClickHouse/pull/7179) ([Alexander
|
||||
Kuzmenkov](https://github.com/akuzm)), [#7376](https://github.com/ClickHouse/ClickHouse/pull/7376)
|
||||
([Amos Bird](https://github.com/amosbird))
|
||||
* Fix undefined behavior in murmurhash32. [#7388](https://github.com/ClickHouse/ClickHouse/pull/7388) ([Amos
|
||||
Bird](https://github.com/amosbird))
|
||||
* Fix undefined behavior in StoragesInfoStream. [#7384](https://github.com/ClickHouse/ClickHouse/pull/7384)
|
||||
([tavplubix](https://github.com/tavplubix))
|
||||
* Fixed constant expressions folding for external database engines (MySQL, ODBC, JDBC). In previous
|
||||
versions it wasn't working for multiple constant expressions and was not working at all for Date,
|
||||
DateTime and UUID. This fixes [#7245](https://github.com/ClickHouse/ClickHouse/issues/7245)
|
||||
[#7252](https://github.com/ClickHouse/ClickHouse/pull/7252)
|
||||
([alexey-milovidov](https://github.com/alexey-milovidov))
|
||||
* Fixing ThreadSanitizer data race error in the LIVE VIEW when accessing no_users_thread variable.
|
||||
[#7353](https://github.com/ClickHouse/ClickHouse/pull/7353)
|
||||
([vzakaznikov](https://github.com/vzakaznikov))
|
||||
* Get rid of malloc symbols in libcommon
|
||||
[#7134](https://github.com/ClickHouse/ClickHouse/pull/7134),
|
||||
[#7065](https://github.com/ClickHouse/ClickHouse/pull/7065) ([Amos
|
||||
Bird](https://github.com/amosbird))
|
||||
* Add global flag ENABLE_LIBRARIES for disabling all libraries.
|
||||
[#7063](https://github.com/ClickHouse/ClickHouse/pull/7063)
|
||||
([proller](https://github.com/proller))
|
||||
|
||||
### Code cleanup
|
||||
* Generalize configuration repository to prepare for DDL for Dictionaries. [#7155](https://github.com/ClickHouse/ClickHouse/pull/7155)
|
||||
([alesapin](https://github.com/alesapin))
|
||||
* Parser for dictionaries DDL without any semantic.
|
||||
[#7209](https://github.com/ClickHouse/ClickHouse/pull/7209)
|
||||
([alesapin](https://github.com/alesapin))
|
||||
* Split ParserCreateQuery into different smaller parsers.
|
||||
[#7253](https://github.com/ClickHouse/ClickHouse/pull/7253)
|
||||
([alesapin](https://github.com/alesapin))
|
||||
* Small refactoring and renaming near external dictionaries.
|
||||
[#7111](https://github.com/ClickHouse/ClickHouse/pull/7111)
|
||||
([alesapin](https://github.com/alesapin))
|
||||
* Refactor some code to prepare for role-based access control. [#7235](https://github.com/ClickHouse/ClickHouse/pull/7235) ([Vitaly
|
||||
Baranov](https://github.com/vitlibar))
|
||||
* Some improvements in DatabaseOrdinary code.
|
||||
[#7086](https://github.com/ClickHouse/ClickHouse/pull/7086) ([Nikita
|
||||
Vasilev](https://github.com/nikvas0))
|
||||
* Do not use iterators in find() and emplace() methods of hash tables.
|
||||
[#7026](https://github.com/ClickHouse/ClickHouse/pull/7026) ([Alexander
|
||||
Kuzmenkov](https://github.com/akuzm))
|
||||
* Fix getMultipleValuesFromConfig in case when parameter root is not empty. [#7374](https://github.com/ClickHouse/ClickHouse/pull/7374)
|
||||
([Mikhail Korotov](https://github.com/millb))
|
||||
* Remove some copy-paste (TemporaryFile and TemporaryFileStream)
|
||||
[#7166](https://github.com/ClickHouse/ClickHouse/pull/7166) ([Artem
|
||||
Zuikov](https://github.com/4ertus2))
|
||||
* Improved code readability a little bit (`MergeTreeData::getActiveContainingPart`).
|
||||
[#7361](https://github.com/ClickHouse/ClickHouse/pull/7361) ([Vladimir
|
||||
Chebotarev](https://github.com/excitoon))
|
||||
* Wait for all scheduled jobs, which are using local objects, if `ThreadPool::schedule(...)` throws
|
||||
an exception. Rename `ThreadPool::schedule(...)` to `ThreadPool::scheduleOrThrowOnError(...)` and
|
||||
fix comments to make obvious that it may throw.
|
||||
[#7350](https://github.com/ClickHouse/ClickHouse/pull/7350)
|
||||
([tavplubix](https://github.com/tavplubix))
|
||||
|
||||
## ClickHouse release 19.15.2.2, 2019-10-01
|
||||
|
||||
### New Feature
|
||||
@ -345,6 +595,13 @@
|
||||
### Security Fix
|
||||
* Fix two vulnerabilities in codecs in decompression phase (malicious user can fabricate compressed data that will lead to buffer overflow in decompression). [#6670](https://github.com/ClickHouse/ClickHouse/pull/6670) ([Artem Zuikov](https://github.com/4ertus2))
|
||||
|
||||
## ClickHouse release 19.11.13.74, 2019-11-01
|
||||
|
||||
### Bug Fix
|
||||
* Fixed rare crash in `ALTER MODIFY COLUMN` and vertical merge when one of merged/altered parts is empty (0 rows). [#6780](https://github.com/ClickHouse/ClickHouse/pull/6780) ([alesapin](https://github.com/alesapin))
|
||||
* Manual update of `SIMDJSON`. This fixes possible flooding of stderr files with bogus json diagnostic messages. [#7548](https://github.com/ClickHouse/ClickHouse/pull/7548) ([Alexander Kazakov](https://github.com/Akazz))
|
||||
* Fixed bug with `mrk` file extension for mutations ([alesapin](https://github.com/alesapin))
|
||||
|
||||
## ClickHouse release 19.11.12.69, 2019-10-02
|
||||
|
||||
### Bug Fix
|
||||
|
@ -13,7 +13,10 @@ foreach(policy
|
||||
endforeach()
|
||||
|
||||
project(ClickHouse)
|
||||
|
||||
include (cmake/arch.cmake)
|
||||
include (cmake/target.cmake)
|
||||
include (cmake/tools.cmake)
|
||||
|
||||
# Ignore export() since we don't use it,
|
||||
# but it gets broken with a global targets via link_libraries()
|
||||
@ -26,8 +29,6 @@ set(CMAKE_LINK_DEPENDS_NO_SHARED 1) # Do not relink all depended targets on .so
|
||||
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Debug;Release;MinSizeRel" CACHE STRING "" FORCE)
|
||||
set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Generate debug library name with a postfix.") # To be consistent with CMakeLists from contrib libs.
|
||||
|
||||
include (cmake/arch.cmake)
|
||||
|
||||
option(ENABLE_IPO "Enable inter-procedural optimization (aka LTO)" OFF) # need cmake 3.9+
|
||||
if(ENABLE_IPO)
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
@ -230,7 +231,6 @@ include(cmake/dbms_glob_sources.cmake)
|
||||
if (OS_LINUX)
|
||||
include(cmake/linux/default_libs.cmake)
|
||||
elseif (OS_DARWIN)
|
||||
include(cmake/darwin/sdk.cmake)
|
||||
include(cmake/darwin/default_libs.cmake)
|
||||
endif ()
|
||||
|
||||
|
@ -13,8 +13,9 @@ ClickHouse is an open-source column-oriented database management system that all
|
||||
* You can also [fill this form](https://forms.yandex.com/surveys/meet-yandex-clickhouse-team/) to meet Yandex ClickHouse team in person.
|
||||
|
||||
## Upcoming Events
|
||||
* [ClickHouse Meetup in Shanghai](https://www.huodongxing.com/event/4483760336000) on October 27.
|
||||
* [ClickHouse Meetup in Tokyo](https://clickhouse.connpass.com/event/147001/) on November 14.
|
||||
* [ClickHouse Meetup in Istanbul](https://www.eventbrite.com/e/clickhouse-meetup-istanbul-create-blazing-fast-experiences-w-clickhouse-tickets-73101120419) on November 19.
|
||||
* [ClickHouse Meetup in Ankara](https://www.eventbrite.com/e/clickhouse-meetup-ankara-create-blazing-fast-experiences-w-clickhouse-tickets-73100530655) on November 21.
|
||||
* [ClickHouse Meetup in Singapore](https://www.meetup.com/Singapore-Clickhouse-Meetup-Group/events/265085331/) on November 23.
|
||||
* [ClickHouse Meetup in San Francisco](https://www.eventbrite.com/e/clickhouse-december-meetup-registration-78642047481) on December 3.
|
||||
|
||||
|
@ -17,6 +17,7 @@ endif ()
|
||||
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(ppc64le.*|PPC64LE.*)")
|
||||
set (ARCH_PPC64LE 1)
|
||||
# FIXME: move this check into tools.cmake
|
||||
if (COMPILER_CLANG OR (COMPILER_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8))
|
||||
message(FATAL_ERROR "Only gcc-8 is supported for powerpc architecture")
|
||||
endif ()
|
||||
|
@ -11,6 +11,14 @@ message(STATUS "Default libraries: ${DEFAULT_LIBS}")
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES ${DEFAULT_LIBS})
|
||||
set(CMAKE_C_STANDARD_LIBRARIES ${DEFAULT_LIBS})
|
||||
|
||||
# Minimal supported SDK version
|
||||
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.14")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.14")
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mmacosx-version-min=10.14")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min=10.14")
|
||||
|
||||
# Global libraries
|
||||
|
||||
add_library(global-libs INTERFACE)
|
||||
|
@ -1,11 +0,0 @@
|
||||
option (SDK_PATH "Path to the SDK to build with" "")
|
||||
|
||||
if (NOT EXISTS "${SDK_PATH}/SDKSettings.plist")
|
||||
message (FATAL_ERROR "Wrong SDK path provided: ${SDK_PATH}")
|
||||
endif ()
|
||||
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isysroot ${SDK_PATH} -mmacosx-version-min=10.14")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isysroot ${SDK_PATH} -mmacosx-version-min=10.14")
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -isysroot ${SDK_PATH} -mmacosx-version-min=10.14")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -isysroot ${SDK_PATH} -mmacosx-version-min=10.14")
|
13
cmake/darwin/toolchain-x86_64.cmake
Normal file
13
cmake/darwin/toolchain-x86_64.cmake
Normal file
@ -0,0 +1,13 @@
|
||||
set (CMAKE_SYSTEM_NAME "Darwin")
|
||||
set (CMAKE_SYSTEM_PROCESSOR "x86_64")
|
||||
set (CMAKE_C_COMPILER_TARGET "x86_64-apple-darwin")
|
||||
set (CMAKE_CXX_COMPILER_TARGET "x86_64-apple-darwin")
|
||||
set (CMAKE_OSX_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/../toolchain/darwin-x86_64")
|
||||
|
||||
set (CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # disable linkage check - it doesn't work in CMake
|
||||
|
||||
set (HAS_PRE_1970_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_PRE_1970_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
||||
set (HAS_POST_2038_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_POST_2038_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
@ -4,6 +4,14 @@ if (ENABLE_CAPNP)
|
||||
|
||||
option (USE_INTERNAL_CAPNP_LIBRARY "Set to FALSE to use system capnproto library instead of bundled" ${NOT_UNBUNDLED})
|
||||
|
||||
if(NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/capnproto/CMakeLists.txt")
|
||||
if(USE_INTERNAL_CAPNP_LIBRARY)
|
||||
message(WARNING "submodule contrib/capnproto is missing. to fix try run: \n git submodule update --init --recursive")
|
||||
endif()
|
||||
set(MISSING_INTERNAL_CAPNP_LIBRARY 1)
|
||||
set(USE_INTERNAL_CAPNP_LIBRARY 0)
|
||||
endif()
|
||||
|
||||
# FIXME: refactor to use `add_library(… IMPORTED)` if possible.
|
||||
if (NOT USE_INTERNAL_CAPNP_LIBRARY)
|
||||
find_library (KJ kj)
|
||||
@ -11,7 +19,7 @@ if (NOT USE_INTERNAL_CAPNP_LIBRARY)
|
||||
find_library (CAPNPC capnpc)
|
||||
|
||||
set (CAPNP_LIBRARIES ${CAPNPC} ${CAPNP} ${KJ})
|
||||
else ()
|
||||
elseif(NOT MISSING_INTERNAL_CAPNP_LIBRARY)
|
||||
add_subdirectory(contrib/capnproto-cmake)
|
||||
|
||||
set (CAPNP_LIBRARIES capnpc)
|
||||
@ -23,4 +31,4 @@ endif ()
|
||||
|
||||
endif ()
|
||||
|
||||
message (STATUS "Using capnp: ${CAPNP_LIBRARIES}")
|
||||
message (STATUS "Using capnp=${USE_CAPNP}: ${CAPNP_LIBRARIES}")
|
||||
|
@ -1,7 +1,8 @@
|
||||
option (ENABLE_ORC "Enable ORC" ${ENABLE_LIBRARIES})
|
||||
|
||||
if(ENABLE_ORC)
|
||||
option (USE_INTERNAL_ORC_LIBRARY "Set to FALSE to use system ORC instead of bundled" ${NOT_UNBUNDLED})
|
||||
include(cmake/find/snappy.cmake)
|
||||
option(USE_INTERNAL_ORC_LIBRARY "Set to FALSE to use system ORC instead of bundled" ${NOT_UNBUNDLED})
|
||||
|
||||
if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/orc/c++/include/orc/OrcFile.hh")
|
||||
if(USE_INTERNAL_ORC_LIBRARY)
|
||||
@ -25,7 +26,7 @@ endif ()
|
||||
|
||||
if (ORC_LIBRARY AND ORC_INCLUDE_DIR)
|
||||
set(USE_ORC 1)
|
||||
elseif(NOT MISSING_INTERNAL_ORC_LIBRARY AND ARROW_LIBRARY) # (LIBGSASL_LIBRARY AND LIBXML2_LIBRARY)
|
||||
elseif(NOT MISSING_INTERNAL_ORC_LIBRARY AND ARROW_LIBRARY AND SNAPPY_LIBRARY) # (LIBGSASL_LIBRARY AND LIBXML2_LIBRARY)
|
||||
set(ORC_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/orc/c++/include")
|
||||
set(ORC_LIBRARY orc)
|
||||
set(USE_ORC 1)
|
||||
|
@ -24,7 +24,10 @@ endif()
|
||||
if(ARROW_INCLUDE_DIR AND PARQUET_INCLUDE_DIR)
|
||||
elseif(NOT MISSING_INTERNAL_PARQUET_LIBRARY AND NOT OS_FREEBSD)
|
||||
include(cmake/find/snappy.cmake)
|
||||
set(CAN_USE_INTERNAL_PARQUET_LIBRARY 1)
|
||||
if(SNAPPY_LIBRARY)
|
||||
set(CAN_USE_INTERNAL_PARQUET_LIBRARY 1)
|
||||
endif()
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
if(NOT USE_INTERNAL_DOUBLE_CONVERSION_LIBRARY)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${DOUBLE_CONVERSION_LIBRARIES})
|
||||
|
@ -8,6 +8,14 @@ if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/poco/CMakeLists.txt")
|
||||
set (MISSING_INTERNAL_POCO_LIBRARY 1)
|
||||
endif ()
|
||||
|
||||
if (NOT ENABLE_LIBRARIES)
|
||||
set (ENABLE_POCO_NETSSL ${ENABLE_LIBRARIES} CACHE BOOL "")
|
||||
set (ENABLE_POCO_MONGODB ${ENABLE_LIBRARIES} CACHE BOOL "")
|
||||
set (ENABLE_POCO_REDIS ${ENABLE_LIBRARIES} CACHE BOOL "")
|
||||
set (ENABLE_POCO_ODBC ${ENABLE_LIBRARIES} CACHE BOOL "")
|
||||
set (ENABLE_POCO_SQL ${ENABLE_LIBRARIES} CACHE BOOL "")
|
||||
endif ()
|
||||
|
||||
set (POCO_COMPONENTS Net XML SQL Data)
|
||||
if (NOT DEFINED ENABLE_POCO_NETSSL OR ENABLE_POCO_NETSSL)
|
||||
list (APPEND POCO_COMPONENTS Crypto NetSSL)
|
||||
|
@ -4,6 +4,11 @@ if (NOT CMAKE_SYSTEM MATCHES "Linux" OR ARCH_ARM OR ARCH_32)
|
||||
set (USE_UNWIND OFF)
|
||||
endif ()
|
||||
|
||||
if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/libunwind/CMakeLists.txt")
|
||||
message(WARNING "submodule contrib/libunwind is missing. to fix try run: \n git submodule update --init --recursive")
|
||||
set (USE_UNWIND OFF)
|
||||
endif ()
|
||||
|
||||
if (USE_UNWIND)
|
||||
add_subdirectory(contrib/libunwind-cmake)
|
||||
set (UNWIND_LIBRARIES unwind)
|
||||
|
@ -5,7 +5,7 @@ set (DEFAULT_LIBS "-nodefaultlibs")
|
||||
|
||||
# We need builtins from Clang's RT even without libcxx - for ubsan+int128.
|
||||
# See https://bugs.llvm.org/show_bug.cgi?id=16404
|
||||
if (COMPILER_CLANG)
|
||||
if (COMPILER_CLANG AND NOT (CMAKE_CROSSCOMPILING AND ARCH_AARCH64))
|
||||
execute_process (COMMAND ${CMAKE_CXX_COMPILER} --print-file-name=libclang_rt.builtins-${CMAKE_SYSTEM_PROCESSOR}.a OUTPUT_VARIABLE BUILTINS_LIBRARY OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
else ()
|
||||
set (BUILTINS_LIBRARY "-lgcc")
|
||||
|
25
cmake/linux/toolchain-aarch64.cmake
Normal file
25
cmake/linux/toolchain-aarch64.cmake
Normal file
@ -0,0 +1,25 @@
|
||||
set (CMAKE_SYSTEM_NAME "Linux")
|
||||
set (CMAKE_SYSTEM_PROCESSOR "aarch64")
|
||||
set (CMAKE_C_COMPILER_TARGET "aarch64-linux-gnu")
|
||||
set (CMAKE_CXX_COMPILER_TARGET "aarch64-linux-gnu")
|
||||
set (CMAKE_ASM_COMPILER_TARGET "aarch64-linux-gnu")
|
||||
set (CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/../toolchain/linux-aarch64/aarch64-linux-gnu/libc")
|
||||
|
||||
# We don't use compiler from toolchain because it's gcc-8, and we provide support only for gcc-9.
|
||||
set (CMAKE_AR "${CMAKE_CURRENT_LIST_DIR}/../toolchain/linux-aarch64/bin/aarch64-linux-gnu-ar" CACHE FILEPATH "" FORCE)
|
||||
set (CMAKE_RANLIB "${CMAKE_CURRENT_LIST_DIR}/../toolchain/linux-aarch64/bin/aarch64-linux-gnu-ranlib" CACHE FILEPATH "" FORCE)
|
||||
|
||||
set (CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} --gcc-toolchain=${CMAKE_CURRENT_LIST_DIR}/../toolchain/linux-aarch64")
|
||||
set (CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS} --gcc-toolchain=${CMAKE_CURRENT_LIST_DIR}/../toolchain/linux-aarch64")
|
||||
set (CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS} --gcc-toolchain=${CMAKE_CURRENT_LIST_DIR}/../toolchain/linux-aarch64")
|
||||
|
||||
set (LINKER_NAME "lld" CACHE STRING "" FORCE)
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
|
||||
set (HAS_PRE_1970_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_PRE_1970_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
||||
set (HAS_POST_2038_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_POST_2038_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
@ -9,62 +9,8 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
add_definitions(-D OS_DARWIN)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set (COMPILER_GCC 1)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set (COMPILER_CLANG 1)
|
||||
endif ()
|
||||
|
||||
if (COMPILER_GCC)
|
||||
# Require minimum version of gcc
|
||||
set (GCC_MINIMUM_VERSION 8)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${GCC_MINIMUM_VERSION} AND NOT CMAKE_VERSION VERSION_LESS 2.8.9)
|
||||
message (FATAL_ERROR "GCC version must be at least ${GCC_MINIMUM_VERSION}. For example, if GCC ${GCC_MINIMUM_VERSION} is available under gcc-${GCC_MINIMUM_VERSION}, g++-${GCC_MINIMUM_VERSION} names, do the following: export CC=gcc-${GCC_MINIMUM_VERSION} CXX=g++-${GCC_MINIMUM_VERSION}; rm -rf CMakeCache.txt CMakeFiles; and re run cmake or ./release.")
|
||||
endif ()
|
||||
elseif (COMPILER_CLANG)
|
||||
# Require minimum version of clang
|
||||
set (CLANG_MINIMUM_VERSION 7)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${CLANG_MINIMUM_VERSION})
|
||||
message (FATAL_ERROR "Clang version must be at least ${CLANG_MINIMUM_VERSION}.")
|
||||
endif ()
|
||||
else ()
|
||||
message (WARNING "You are using an unsupported compiler. Compilation has only been tested with Clang 6+ and GCC 7+.")
|
||||
endif ()
|
||||
|
||||
string(REGEX MATCH "-?[0-9]+(.[0-9]+)?$" COMPILER_POSTFIX ${CMAKE_CXX_COMPILER})
|
||||
|
||||
if (OS_LINUX)
|
||||
find_program (LLD_PATH NAMES "lld${COMPILER_POSTFIX}" "lld")
|
||||
find_program (GOLD_PATH NAMES "ld.gold" "gold")
|
||||
endif()
|
||||
|
||||
option (LINKER_NAME "Linker name or full path")
|
||||
if (NOT LINKER_NAME)
|
||||
if (COMPILER_CLANG AND LLD_PATH)
|
||||
set (LINKER_NAME "lld")
|
||||
elseif (GOLD_PATH)
|
||||
set (LINKER_NAME "gold")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (LINKER_NAME)
|
||||
message(STATUS "Using linker: ${LINKER_NAME} (selected from: LLD_PATH=${LLD_PATH}; GOLD_PATH=${GOLD_PATH}; COMPILER_POSTFIX=${COMPILER_POSTFIX})")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
if (OS_DARWIN)
|
||||
set (CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
set (CMAKE_C_COMPILER_TARGET x86_64-apple-darwin)
|
||||
set (CMAKE_CXX_COMPILER_TARGET x86_64-apple-darwin)
|
||||
|
||||
set (HAS_PRE_1970_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_PRE_1970_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
||||
set (HAS_POST_2038_EXITCODE "0" CACHE STRING "Result from TRY_RUN" FORCE)
|
||||
set (HAS_POST_2038_EXITCODE__TRYRUN_OUTPUT "" CACHE STRING "Output from TRY_RUN" FORCE)
|
||||
|
||||
# FIXME: broken dependencies
|
||||
set (USE_SNAPPY OFF CACHE INTERNAL "")
|
||||
set (ENABLE_SSL OFF CACHE INTERNAL "")
|
||||
@ -73,12 +19,19 @@ if (CMAKE_CROSSCOMPILING)
|
||||
set (ENABLE_READLINE OFF CACHE INTERNAL "")
|
||||
set (ENABLE_ICU OFF CACHE INTERNAL "")
|
||||
set (ENABLE_FASTOPS OFF CACHE INTERNAL "")
|
||||
|
||||
message (STATUS "Cross-compiling for Darwin")
|
||||
elseif (OS_LINUX)
|
||||
if (ARCH_AARCH64)
|
||||
# FIXME: broken dependencies
|
||||
set (ENABLE_PROTOBUF OFF CACHE INTERNAL "")
|
||||
set (ENABLE_PARQUET OFF CACHE INTERNAL "")
|
||||
set (ENABLE_MYSQL OFF CACHE INTERNAL "")
|
||||
endif ()
|
||||
else ()
|
||||
message (FATAL_ERROR "Trying to cross-compile to unsupported target: ${CMAKE_SYSTEM_NAME}!")
|
||||
message (FATAL_ERROR "Trying to cross-compile to unsupported system: ${CMAKE_SYSTEM_NAME}!")
|
||||
endif ()
|
||||
|
||||
# Don't know why but CXX_STANDARD doesn't work for cross-compilation
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
|
||||
message (STATUS "Cross-compiling for target: ${CMAKE_CXX_COMPILE_TARGET}")
|
||||
endif ()
|
||||
|
2
cmake/toolchain/darwin-x86_64/README.txt
Normal file
2
cmake/toolchain/darwin-x86_64/README.txt
Normal file
@ -0,0 +1,2 @@
|
||||
wget https://github.com/phracker/MacOSX-SDKs/releases/download/10.14-beta4/MacOSX10.14.sdk.tar.xz
|
||||
tar --strip-components=1 xJf MacOSX10.14.sdk.tar.xz
|
2
cmake/toolchain/linux-aarch64/README.txt
Normal file
2
cmake/toolchain/linux-aarch64/README.txt
Normal file
@ -0,0 +1,2 @@
|
||||
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz?revision=2e88a73f-d233-4f96-b1f4-d8b36e9bb0b9&la=en -O gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz
|
||||
tar --strip-components=1 xJf gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu.tar.xz
|
41
cmake/tools.cmake
Normal file
41
cmake/tools.cmake
Normal file
@ -0,0 +1,41 @@
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set (COMPILER_GCC 1)
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
|
||||
set (COMPILER_CLANG 1)
|
||||
endif ()
|
||||
|
||||
if (COMPILER_GCC)
|
||||
# Require minimum version of gcc
|
||||
set (GCC_MINIMUM_VERSION 8)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${GCC_MINIMUM_VERSION} AND NOT CMAKE_VERSION VERSION_LESS 2.8.9)
|
||||
message (FATAL_ERROR "GCC version must be at least ${GCC_MINIMUM_VERSION}. For example, if GCC ${GCC_MINIMUM_VERSION} is available under gcc-${GCC_MINIMUM_VERSION}, g++-${GCC_MINIMUM_VERSION} names, do the following: export CC=gcc-${GCC_MINIMUM_VERSION} CXX=g++-${GCC_MINIMUM_VERSION}; rm -rf CMakeCache.txt CMakeFiles; and re run cmake or ./release.")
|
||||
endif ()
|
||||
elseif (COMPILER_CLANG)
|
||||
# Require minimum version of clang
|
||||
set (CLANG_MINIMUM_VERSION 7)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${CLANG_MINIMUM_VERSION})
|
||||
message (FATAL_ERROR "Clang version must be at least ${CLANG_MINIMUM_VERSION}.")
|
||||
endif ()
|
||||
else ()
|
||||
message (WARNING "You are using an unsupported compiler. Compilation has only been tested with Clang 6+ and GCC 7+.")
|
||||
endif ()
|
||||
|
||||
option (LINKER_NAME "Linker name or full path")
|
||||
|
||||
find_program (LLD_PATH NAMES "ld.lld" "lld")
|
||||
find_program (GOLD_PATH NAMES "ld.gold" "gold")
|
||||
|
||||
if (NOT LINKER_NAME)
|
||||
if (LLD_PATH)
|
||||
set (LINKER_NAME "lld")
|
||||
elseif (GOLD_PATH)
|
||||
set (LINKER_NAME "gold")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (LINKER_NAME)
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}")
|
||||
|
||||
message(STATUS "Using custom linker by name: ${LINKER_NAME}")
|
||||
endif ()
|
10
contrib/CMakeLists.txt
vendored
10
contrib/CMakeLists.txt
vendored
@ -124,7 +124,7 @@ if (USE_INTERNAL_SSL_LIBRARY)
|
||||
add_library(OpenSSL::SSL ALIAS ${OPENSSL_SSL_LIBRARY})
|
||||
endif ()
|
||||
|
||||
if (ENABLE_MYSQL AND USE_INTERNAL_MYSQL_LIBRARY)
|
||||
function(mysql_support)
|
||||
set(CLIENT_PLUGIN_CACHING_SHA2_PASSWORD STATIC)
|
||||
set(CLIENT_PLUGIN_SHA256_PASSWORD STATIC)
|
||||
set(CLIENT_PLUGIN_REMOTE_IO OFF)
|
||||
@ -136,7 +136,15 @@ if (ENABLE_MYSQL AND USE_INTERNAL_MYSQL_LIBRARY)
|
||||
if (GLIBC_COMPATIBILITY)
|
||||
set(LIBM glibc-compatibility)
|
||||
endif()
|
||||
if (USE_INTERNAL_ZLIB_LIBRARY)
|
||||
set(ZLIB_FOUND ON)
|
||||
set(ZLIB_LIBRARY zlibstatic)
|
||||
set(WITH_EXTERNAL_ZLIB ON)
|
||||
endif()
|
||||
add_subdirectory (mariadb-connector-c)
|
||||
endfunction()
|
||||
if (ENABLE_MYSQL AND USE_INTERNAL_MYSQL_LIBRARY)
|
||||
mysql_support()
|
||||
endif ()
|
||||
|
||||
if (USE_INTERNAL_RDKAFKA_LIBRARY)
|
||||
|
@ -70,6 +70,14 @@ add_custom_command(OUTPUT orc_proto.pb.h orc_proto.pb.cc
|
||||
--cpp_out="${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${PROTO_DIR}/orc_proto.proto")
|
||||
|
||||
# arrow-cmake cmake file calling orc cmake subroutine which detects certain compiler features.
|
||||
# Apple Clang compiler failed to compile this code without specifying c++11 standard.
|
||||
# As result these compiler features detected as absent. In result it failed to compile orc itself.
|
||||
# In orc makefile there is code that sets flags, but arrow-cmake ignores these flags.
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set (CXX11_FLAGS "-std=c++0x")
|
||||
endif()
|
||||
|
||||
include(${ClickHouse_SOURCE_DIR}/contrib/orc/cmake_modules/CheckSourceCompiles.cmake)
|
||||
include(orc_check.cmake)
|
||||
configure_file("${ORC_INCLUDE_DIR}/orc/orc-config.hh.in" "${ORC_BUILD_INCLUDE_DIR}/orc/orc-config.hh")
|
||||
|
@ -44,7 +44,7 @@ target_include_directories(cxx SYSTEM BEFORE PUBLIC $<BUILD_INTERFACE:${LIBCXX_S
|
||||
target_compile_definitions(cxx PRIVATE -D_LIBCPP_BUILDING_LIBRARY -DLIBCXX_BUILDING_LIBCXXABI)
|
||||
|
||||
target_compile_options(cxx PUBLIC -nostdinc++ -Wno-reserved-id-macro)
|
||||
if (OS_DARWIN AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
|
||||
if (OS_DARWIN AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9) AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11))
|
||||
target_compile_options(cxx PUBLIC -Wno-ctad-maybe-unsupported)
|
||||
endif ()
|
||||
|
||||
|
@ -130,8 +130,8 @@ list (APPEND dbms_headers
|
||||
|
||||
list (APPEND dbms_sources src/TableFunctions/ITableFunction.cpp src/TableFunctions/TableFunctionFactory.cpp)
|
||||
list (APPEND dbms_headers src/TableFunctions/ITableFunction.h src/TableFunctions/TableFunctionFactory.h)
|
||||
list (APPEND dbms_sources src/Dictionaries/DictionaryFactory.cpp src/Dictionaries/DictionarySourceFactory.cpp src/Dictionaries/DictionaryStructure.cpp)
|
||||
list (APPEND dbms_headers src/Dictionaries/DictionaryFactory.h src/Dictionaries/DictionarySourceFactory.h src/Dictionaries/DictionaryStructure.h)
|
||||
list (APPEND dbms_sources src/Dictionaries/DictionaryFactory.cpp src/Dictionaries/DictionarySourceFactory.cpp src/Dictionaries/DictionaryStructure.cpp src/Dictionaries/getDictionaryConfigurationFromAST.cpp)
|
||||
list (APPEND dbms_headers src/Dictionaries/DictionaryFactory.h src/Dictionaries/DictionarySourceFactory.h src/Dictionaries/DictionaryStructure.h src/Dictionaries/getDictionaryConfigurationFromAST.h)
|
||||
|
||||
if (NOT ENABLE_SSL)
|
||||
list (REMOVE_ITEM clickhouse_common_io_sources src/Common/OpenSSLHelpers.cpp)
|
||||
@ -425,6 +425,11 @@ endif()
|
||||
if (USE_JEMALLOC)
|
||||
dbms_target_include_directories (SYSTEM BEFORE PRIVATE ${JEMALLOC_INCLUDE_DIR}) # used in Interpreters/AsynchronousMetrics.cpp
|
||||
target_include_directories (clickhouse_new_delete SYSTEM BEFORE PRIVATE ${JEMALLOC_INCLUDE_DIR})
|
||||
|
||||
if(NOT MAKE_STATIC_LIBRARIES AND ${JEMALLOC_LIBRARIES} MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$")
|
||||
# mallctl in dbms/src/Interpreters/AsynchronousMetrics.cpp
|
||||
target_link_libraries(clickhouse_interpreters PRIVATE ${JEMALLOC_LIBRARIES})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
dbms_target_include_directories (PUBLIC ${DBMS_INCLUDE_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src/Formats/include)
|
||||
|
@ -365,7 +365,7 @@ private:
|
||||
Stopwatch watch;
|
||||
RemoteBlockInputStream stream(
|
||||
*(*connection_entries[connection_index]),
|
||||
query, {}, global_context, &settings, nullptr, Tables(), query_processing_stage);
|
||||
query, {}, global_context, &settings, nullptr, Scalars(), Tables(), query_processing_stage);
|
||||
|
||||
Progress progress;
|
||||
stream.setProgressCallback([&progress](const Progress & value) { progress.incrementPiecewiseAtomically(value); });
|
||||
|
@ -89,6 +89,40 @@
|
||||
#define DISABLE_LINE_WRAPPING "\033[?7l"
|
||||
#define ENABLE_LINE_WRAPPING "\033[?7h"
|
||||
|
||||
#if USE_READLINE && RL_VERSION_MAJOR >= 7
|
||||
|
||||
#define BRACK_PASTE_PREF "\033[200~"
|
||||
#define BRACK_PASTE_SUFF "\033[201~"
|
||||
|
||||
#define BRACK_PASTE_LAST '~'
|
||||
#define BRACK_PASTE_SLEN 6
|
||||
|
||||
/// Make sure we don't get ^J for the enter character.
|
||||
/// This handler also bypasses some unused macro/event checkings.
|
||||
static int clickhouse_rl_bracketed_paste_begin(int /* count */, int /* key */)
|
||||
{
|
||||
std::string buf;
|
||||
buf.reserve(128);
|
||||
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
SCOPE_EXIT(RL_UNSETSTATE(RL_STATE_MOREINPUT));
|
||||
char c;
|
||||
while ((c = rl_read_key()) >= 0)
|
||||
{
|
||||
if (c == '\r' || c == '\n')
|
||||
c = '\n';
|
||||
buf.push_back(c);
|
||||
if (buf.size() >= BRACK_PASTE_SLEN && c == BRACK_PASTE_LAST && buf.substr(buf.size() - BRACK_PASTE_SLEN) == BRACK_PASTE_SUFF)
|
||||
{
|
||||
buf.resize(buf.size() - BRACK_PASTE_SLEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return static_cast<size_t>(rl_insert_text(buf.c_str())) == buf.size() ? 0 : 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
@ -462,6 +496,18 @@ private:
|
||||
if (rl_initialize())
|
||||
throw Exception("Cannot initialize readline", ErrorCodes::CANNOT_READLINE);
|
||||
|
||||
#if RL_VERSION_MAJOR >= 7
|
||||
/// When bracketed paste mode is set, pasted text is bracketed with control sequences so
|
||||
/// that the program can differentiate pasted text from typed-in text. This helps
|
||||
/// clickhouse-client so that without -m flag, one can still paste multiline queries, and
|
||||
/// possibly get better pasting performance. See https://cirw.in/blog/bracketed-paste for
|
||||
/// more details.
|
||||
rl_variable_bind("enable-bracketed-paste", "on");
|
||||
|
||||
/// Use our bracketed paste handler to get better user experience. See comments above.
|
||||
rl_bind_keyseq(BRACK_PASTE_PREF, clickhouse_rl_bracketed_paste_begin);
|
||||
#endif
|
||||
|
||||
auto clear_prompt_or_exit = [](int)
|
||||
{
|
||||
/// This is signal safe.
|
||||
@ -632,7 +678,8 @@ private:
|
||||
/// If the user restarts the client then after pressing the "up" button
|
||||
/// every line of the query will be displayed separately.
|
||||
std::string logged_query = input;
|
||||
std::replace(logged_query.begin(), logged_query.end(), '\n', ' ');
|
||||
if (config().has("multiline"))
|
||||
std::replace(logged_query.begin(), logged_query.end(), '\n', ' ');
|
||||
add_history(logged_query.c_str());
|
||||
|
||||
#if USE_READLINE && HAVE_READLINE_HISTORY
|
||||
|
@ -38,12 +38,16 @@ namespace
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SQL_TINYINT:
|
||||
return factory.get("Int8");
|
||||
case SQL_INTEGER:
|
||||
return factory.get("Int32");
|
||||
case SQL_SMALLINT:
|
||||
return factory.get("Int16");
|
||||
case SQL_BIGINT:
|
||||
return factory.get("Int64");
|
||||
case SQL_FLOAT:
|
||||
return factory.get("Float32");
|
||||
return factory.get("Float64");
|
||||
case SQL_REAL:
|
||||
return factory.get("Float32");
|
||||
case SQL_DOUBLE:
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
void set(const std::string & key, std::string value, bool wrap = true);
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_arithmetic_v<T>> set(const std::string key, T value)
|
||||
std::enable_if_t<is_arithmetic_v<T>> set(const std::string key, T value)
|
||||
{
|
||||
set(key, std::to_string(value), /*wrap= */ false);
|
||||
}
|
||||
|
@ -10,13 +10,11 @@ set(CLICKHOUSE_SERVER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TCPHandler.cpp
|
||||
)
|
||||
|
||||
if (USE_SSL)
|
||||
set(CLICKHOUSE_SERVER_SOURCES
|
||||
${CLICKHOUSE_SERVER_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandlerFactory.cpp
|
||||
)
|
||||
endif ()
|
||||
set(CLICKHOUSE_SERVER_SOURCES
|
||||
${CLICKHOUSE_SERVER_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandlerFactory.cpp
|
||||
)
|
||||
|
||||
set(CLICKHOUSE_SERVER_LINK PRIVATE clickhouse_dictionaries clickhouse_common_io clickhouse_common_config clickhouse_common_zookeeper clickhouse_parsers string_utils PUBLIC daemon PRIVATE clickhouse_storages_system clickhouse_functions clickhouse_aggregate_functions clickhouse_table_functions ${Poco_Net_LIBRARY})
|
||||
if (USE_POCO_NETSSL)
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <Common/config.h>
|
||||
#if USE_SSL
|
||||
#include "MySQLHandler.h"
|
||||
|
||||
#include "MySQLHandler.h"
|
||||
#include <limits>
|
||||
#include <ext/scope_guard.h>
|
||||
#include <Columns/ColumnVector.h>
|
||||
@ -15,37 +14,39 @@
|
||||
#include <IO/ReadBufferFromPocoSocket.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/WriteBufferFromPocoSocket.h>
|
||||
#include <Poco/Crypto/CipherFactory.h>
|
||||
#include <Poco/Crypto/RSAKey.h>
|
||||
#include <Poco/Net/SecureStreamSocket.h>
|
||||
#include <Poco/Net/SSLManager.h>
|
||||
#include <Storages/IStorage.h>
|
||||
|
||||
#if USE_POCO_NETSSL
|
||||
#include <Poco/Net/SecureStreamSocket.h>
|
||||
#include <Poco/Net/SSLManager.h>
|
||||
#include <Poco/Crypto/CipherFactory.h>
|
||||
#include <Poco/Crypto/RSAKey.h>
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace MySQLProtocol;
|
||||
|
||||
|
||||
#if USE_POCO_NETSSL
|
||||
using Poco::Net::SecureStreamSocket;
|
||||
using Poco::Net::SSLManager;
|
||||
|
||||
#endif
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int MYSQL_CLIENT_INSUFFICIENT_CAPABILITIES;
|
||||
extern const int OPENSSL_ERROR;
|
||||
extern const int SUPPORT_IS_DISABLED;
|
||||
}
|
||||
|
||||
MySQLHandler::MySQLHandler(IServer & server_, const Poco::Net::StreamSocket & socket_, RSA & public_key_, RSA & private_key_, bool ssl_enabled, size_t connection_id_)
|
||||
MySQLHandler::MySQLHandler(IServer & server_, const Poco::Net::StreamSocket & socket_,
|
||||
bool ssl_enabled, size_t connection_id_)
|
||||
: Poco::Net::TCPServerConnection(socket_)
|
||||
, server(server_)
|
||||
, log(&Poco::Logger::get("MySQLHandler"))
|
||||
, connection_context(server.context())
|
||||
, connection_id(connection_id_)
|
||||
, public_key(public_key_)
|
||||
, private_key(private_key_)
|
||||
, auth_plugin(new MySQLProtocol::Authentication::Native41())
|
||||
{
|
||||
server_capability_flags = CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | CLIENT_PLUGIN_AUTH | CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | CLIENT_CONNECT_WITH_DB | CLIENT_DEPRECATE_EOF;
|
||||
@ -197,21 +198,7 @@ void MySQLHandler::finishHandshake(MySQLProtocol::HandshakeResponse & packet)
|
||||
|
||||
if (payload_size == SSL_REQUEST_PAYLOAD_SIZE)
|
||||
{
|
||||
read_bytes(packet_size); /// Reading rest SSLRequest.
|
||||
SSLRequest ssl_request;
|
||||
ReadBufferFromMemory payload(buf, pos);
|
||||
payload.ignore(PACKET_HEADER_SIZE);
|
||||
ssl_request.readPayload(payload);
|
||||
connection_context.mysql.client_capabilities = ssl_request.capability_flags;
|
||||
connection_context.mysql.max_packet_size = ssl_request.max_packet_size ? ssl_request.max_packet_size : MAX_PACKET_LENGTH;
|
||||
secure_connection = true;
|
||||
ss = std::make_shared<SecureStreamSocket>(SecureStreamSocket::attach(socket(), SSLManager::instance().defaultServerContext()));
|
||||
in = std::make_shared<ReadBufferFromPocoSocket>(*ss);
|
||||
out = std::make_shared<WriteBufferFromPocoSocket>(*ss);
|
||||
connection_context.mysql.sequence_id = 2;
|
||||
packet_sender = std::make_shared<PacketSender>(*in, *out, connection_context.mysql.sequence_id);
|
||||
packet_sender->max_packet_size = connection_context.mysql.max_packet_size;
|
||||
packet_sender->receivePacket(packet); /// Reading HandshakeResponse from secure socket.
|
||||
finishHandshakeSSL(packet_size, buf, pos, read_bytes, packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -232,7 +219,9 @@ void MySQLHandler::authenticate(const String & user_name, const String & auth_pl
|
||||
// For compatibility with JavaScript MySQL client, Native41 authentication plugin is used when possible (if password is specified using double SHA1). Otherwise SHA256 plugin is used.
|
||||
auto user = connection_context.getUser(user_name);
|
||||
if (user->authentication.getType() != DB::Authentication::DOUBLE_SHA1_PASSWORD)
|
||||
auth_plugin = std::make_unique<MySQLProtocol::Authentication::Sha256Password>(public_key, private_key, log);
|
||||
{
|
||||
authPluginSSL();
|
||||
}
|
||||
|
||||
try {
|
||||
std::optional<String> auth_response = auth_plugin_name == auth_plugin->getName() ? std::make_optional<String>(initial_auth_response) : std::nullopt;
|
||||
@ -302,5 +291,47 @@ void MySQLHandler::comQuery(ReadBuffer & payload)
|
||||
packet_sender->sendPacket(OK_Packet(0x00, client_capability_flags, 0, 0, 0), true);
|
||||
}
|
||||
|
||||
void MySQLHandler::authPluginSSL()
|
||||
{
|
||||
throw Exception("Compiled without SSL", ErrorCodes::SUPPORT_IS_DISABLED);
|
||||
}
|
||||
|
||||
void MySQLHandler::finishHandshakeSSL([[maybe_unused]] size_t packet_size, [[maybe_unused]] char * buf, [[maybe_unused]] size_t pos, [[maybe_unused]] std::function<void(size_t)> read_bytes, [[maybe_unused]] MySQLProtocol::HandshakeResponse & packet)
|
||||
{
|
||||
throw Exception("Compiled without SSL", ErrorCodes::SUPPORT_IS_DISABLED);
|
||||
}
|
||||
|
||||
#if USE_SSL && USE_POCO_NETSSL
|
||||
MySQLHandlerSSL::MySQLHandlerSSL(IServer & server_, const Poco::Net::StreamSocket & socket_, bool ssl_enabled, size_t connection_id_, RSA & public_key_, RSA & private_key_)
|
||||
: MySQLHandler(server_, socket_, ssl_enabled, connection_id_)
|
||||
, public_key(public_key_)
|
||||
, private_key(private_key_)
|
||||
{}
|
||||
|
||||
void MySQLHandlerSSL::authPluginSSL()
|
||||
{
|
||||
auth_plugin = std::make_unique<MySQLProtocol::Authentication::Sha256Password>(public_key, private_key, log);
|
||||
}
|
||||
|
||||
void MySQLHandlerSSL::finishHandshakeSSL(size_t packet_size, char * buf, size_t pos, std::function<void(size_t)> read_bytes, MySQLProtocol::HandshakeResponse & packet)
|
||||
{
|
||||
read_bytes(packet_size); /// Reading rest SSLRequest.
|
||||
SSLRequest ssl_request;
|
||||
ReadBufferFromMemory payload(buf, pos);
|
||||
payload.ignore(PACKET_HEADER_SIZE);
|
||||
ssl_request.readPayload(payload);
|
||||
connection_context.mysql.client_capabilities = ssl_request.capability_flags;
|
||||
connection_context.mysql.max_packet_size = ssl_request.max_packet_size ? ssl_request.max_packet_size : MAX_PACKET_LENGTH;
|
||||
secure_connection = true;
|
||||
ss = std::make_shared<SecureStreamSocket>(SecureStreamSocket::attach(socket(), SSLManager::instance().defaultServerContext()));
|
||||
in = std::make_shared<ReadBufferFromPocoSocket>(*ss);
|
||||
out = std::make_shared<WriteBufferFromPocoSocket>(*ss);
|
||||
connection_context.mysql.sequence_id = 2;
|
||||
packet_sender = std::make_shared<PacketSender>(*in, *out, connection_context.mysql.sequence_id);
|
||||
packet_sender->max_packet_size = connection_context.mysql.max_packet_size;
|
||||
packet_sender->receivePacket(packet); /// Reading HandshakeResponse from secure socket.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
#include <Common/config.h>
|
||||
#if USE_SSL
|
||||
|
||||
#include <Poco/Net/TCPServerConnection.h>
|
||||
#include <Poco/Net/SecureStreamSocket.h>
|
||||
#include <Common/getFQDNOrHostName.h>
|
||||
#include <Core/MySQLProtocol.h>
|
||||
#include "IServer.h"
|
||||
|
||||
#if USE_POCO_NETSSL
|
||||
#include <Poco/Net/SecureStreamSocket.h>
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -16,7 +16,7 @@ namespace DB
|
||||
class MySQLHandler : public Poco::Net::TCPServerConnection
|
||||
{
|
||||
public:
|
||||
MySQLHandler(IServer & server_, const Poco::Net::StreamSocket & socket_, RSA & public_key_, RSA & private_key_, bool ssl_enabled, size_t connection_id_);
|
||||
MySQLHandler(IServer & server_, const Poco::Net::StreamSocket & socket_, bool ssl_enabled, size_t connection_id_);
|
||||
|
||||
void run() final;
|
||||
|
||||
@ -34,28 +34,47 @@ private:
|
||||
|
||||
void authenticate(const String & user_name, const String & auth_plugin_name, const String & auth_response);
|
||||
|
||||
virtual void authPluginSSL();
|
||||
virtual void finishHandshakeSSL(size_t packet_size, char * buf, size_t pos, std::function<void(size_t)> read_bytes, MySQLProtocol::HandshakeResponse & packet);
|
||||
|
||||
IServer & server;
|
||||
|
||||
protected:
|
||||
Poco::Logger * log;
|
||||
|
||||
Context connection_context;
|
||||
|
||||
std::shared_ptr<MySQLProtocol::PacketSender> packet_sender;
|
||||
|
||||
private:
|
||||
size_t connection_id = 0;
|
||||
|
||||
size_t server_capability_flags = 0;
|
||||
size_t client_capability_flags = 0;
|
||||
|
||||
RSA & public_key;
|
||||
RSA & private_key;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<MySQLProtocol::Authentication::IPlugin> auth_plugin;
|
||||
|
||||
std::shared_ptr<Poco::Net::SecureStreamSocket> ss;
|
||||
std::shared_ptr<ReadBuffer> in;
|
||||
std::shared_ptr<WriteBuffer> out;
|
||||
|
||||
bool secure_connection = false;
|
||||
};
|
||||
|
||||
}
|
||||
#if USE_SSL && USE_POCO_NETSSL
|
||||
class MySQLHandlerSSL : public MySQLHandler
|
||||
{
|
||||
public:
|
||||
MySQLHandlerSSL(IServer & server_, const Poco::Net::StreamSocket & socket_, bool ssl_enabled, size_t connection_id_, RSA & public_key_, RSA & private_key_);
|
||||
|
||||
private:
|
||||
void authPluginSSL() override;
|
||||
void finishHandshakeSSL(size_t packet_size, char * buf, size_t pos, std::function<void(size_t)> read_bytes, MySQLProtocol::HandshakeResponse & packet) override;
|
||||
|
||||
RSA & public_key;
|
||||
RSA & private_key;
|
||||
std::shared_ptr<Poco::Net::SecureStreamSocket> ss;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "MySQLHandlerFactory.h"
|
||||
#if USE_POCO_NETSSL && USE_SSL
|
||||
#include <Common/OpenSSLHelpers.h>
|
||||
#include <Poco/Net/SSLManager.h>
|
||||
#include <Poco/Net/TCPServerConnectionFactory.h>
|
||||
#include <Poco/Util/Application.h>
|
||||
#include <common/logger_useful.h>
|
||||
@ -9,6 +7,10 @@
|
||||
#include "IServer.h"
|
||||
#include "MySQLHandler.h"
|
||||
|
||||
#if USE_POCO_NETSSL
|
||||
#include <Poco/Net/SSLManager.h>
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
@ -24,6 +26,8 @@ MySQLHandlerFactory::MySQLHandlerFactory(IServer & server_)
|
||||
: server(server_)
|
||||
, log(&Logger::get("MySQLHandlerFactory"))
|
||||
{
|
||||
|
||||
#if USE_POCO_NETSSL
|
||||
try
|
||||
{
|
||||
Poco::Net::SSLManager::instance().defaultServerContext();
|
||||
@ -33,7 +37,9 @@ MySQLHandlerFactory::MySQLHandlerFactory(IServer & server_)
|
||||
LOG_INFO(log, "Failed to create SSL context. SSL will be disabled. Error: " << getCurrentExceptionMessage(false));
|
||||
ssl_enabled = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_SSL
|
||||
/// Reading rsa keys for SHA256 authentication plugin.
|
||||
try
|
||||
{
|
||||
@ -44,8 +50,10 @@ MySQLHandlerFactory::MySQLHandlerFactory(IServer & server_)
|
||||
LOG_WARNING(log, "Failed to read RSA keys. Error: " << getCurrentExceptionMessage(false));
|
||||
generateRSAKeys();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_SSL
|
||||
void MySQLHandlerFactory::readRSAKeys()
|
||||
{
|
||||
const Poco::Util::LayeredConfiguration & config = Poco::Util::Application::instance().config();
|
||||
@ -113,13 +121,18 @@ void MySQLHandlerFactory::generateRSAKeys()
|
||||
if (!private_key)
|
||||
throw Exception("Failed to copy RSA key. Error: " + getOpenSSLErrors(), ErrorCodes::OPENSSL_ERROR);
|
||||
}
|
||||
#endif
|
||||
|
||||
Poco::Net::TCPServerConnection * MySQLHandlerFactory::createConnection(const Poco::Net::StreamSocket & socket)
|
||||
{
|
||||
size_t connection_id = last_connection_id++;
|
||||
LOG_TRACE(log, "MySQL connection. Id: " << connection_id << ". Address: " << socket.peerAddress().toString());
|
||||
return new MySQLHandler(server, socket, *public_key, *private_key, ssl_enabled, connection_id);
|
||||
#if USE_POCO_NETSSL && USE_SSL
|
||||
return new MySQLHandlerSSL(server, socket, ssl_enabled, connection_id, *public_key, *private_key);
|
||||
#else
|
||||
return new MySQLHandler(server, socket, ssl_enabled, connection_id);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/config.h>
|
||||
#if USE_POCO_NETSSL && USE_SSL
|
||||
|
||||
#include <Poco/Net/TCPServerConnectionFactory.h>
|
||||
#include <atomic>
|
||||
#include <openssl/rsa.h>
|
||||
#include "IServer.h"
|
||||
#if USE_SSL
|
||||
#include <openssl/rsa.h>
|
||||
#endif
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -17,6 +17,7 @@ private:
|
||||
IServer & server;
|
||||
Poco::Logger * log;
|
||||
|
||||
#if USE_SSL
|
||||
struct RSADeleter
|
||||
{
|
||||
void operator()(RSA * ptr) { RSA_free(ptr); }
|
||||
@ -27,6 +28,9 @@ private:
|
||||
RSAPtr private_key;
|
||||
|
||||
bool ssl_enabled = true;
|
||||
#else
|
||||
bool ssl_enabled = false;
|
||||
#endif
|
||||
|
||||
std::atomic<size_t> last_connection_id = 0;
|
||||
public:
|
||||
@ -40,4 +44,3 @@ public:
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -44,7 +44,7 @@ void ReplicasStatusHandler::handleRequest(Poco::Net::HTTPServerRequest & request
|
||||
if (db.second->getEngineName() == "Lazy")
|
||||
continue;
|
||||
|
||||
for (auto iterator = db.second->getIterator(context); iterator->isValid(); iterator->next())
|
||||
for (auto iterator = db.second->getTablesIterator(context); iterator->isValid(); iterator->next())
|
||||
{
|
||||
auto & table = iterator->table();
|
||||
StorageReplicatedMergeTree * table_replicated = dynamic_cast<StorageReplicatedMergeTree *>(table.get());
|
||||
|
@ -37,10 +37,12 @@
|
||||
#include <Interpreters/AsynchronousMetrics.h>
|
||||
#include <Interpreters/DDLWorker.h>
|
||||
#include <Interpreters/ExternalDictionariesLoader.h>
|
||||
#include <Interpreters/ExternalModelsLoader.h>
|
||||
#include <Interpreters/ProcessList.h>
|
||||
#include <Interpreters/loadMetadata.h>
|
||||
#include <Interpreters/DNSCacheUpdater.h>
|
||||
#include <Interpreters/SystemLog.cpp>
|
||||
#include <Interpreters/ExternalLoaderXMLConfigRepository.h>
|
||||
#include <Storages/StorageReplicatedMergeTree.h>
|
||||
#include <Storages/System/attachSystemTables.h>
|
||||
#include <AggregateFunctions/registerAggregateFunctions.h>
|
||||
@ -55,7 +57,7 @@
|
||||
#include "TCPHandlerFactory.h"
|
||||
#include "Common/config_version.h"
|
||||
#include <Common/SensitiveDataMasker.h>
|
||||
|
||||
#include "MySQLHandlerFactory.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include <Common/hasLinuxCapability.h>
|
||||
@ -63,7 +65,6 @@
|
||||
#endif
|
||||
|
||||
#if USE_POCO_NETSSL
|
||||
#include "MySQLHandlerFactory.h"
|
||||
#include <Poco/Net/Context.h>
|
||||
#include <Poco/Net/SecureServerSocket.h>
|
||||
#endif
|
||||
@ -920,6 +921,12 @@ int Server::main(const std::vector<std::string> & /*args*/)
|
||||
global_context->tryCreateEmbeddedDictionaries();
|
||||
global_context->getExternalDictionariesLoader().enableAlwaysLoadEverything(true);
|
||||
}
|
||||
|
||||
auto dictionaries_repository = std::make_unique<ExternalLoaderXMLConfigRepository>(config(), "dictionaries_config");
|
||||
global_context->getExternalDictionariesLoader().addConfigRepository("", std::move(dictionaries_repository));
|
||||
|
||||
auto models_repository = std::make_unique<ExternalLoaderXMLConfigRepository>(config(), "models_config");
|
||||
global_context->getExternalModelsLoader().addConfigRepository("", std::move(models_repository));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -530,7 +530,8 @@ void TCPHandler::processOrdinaryQuery()
|
||||
sendLogs();
|
||||
}
|
||||
|
||||
sendData(block);
|
||||
if (!block || !state.io.null_format)
|
||||
sendData(block);
|
||||
if (!block)
|
||||
break;
|
||||
}
|
||||
@ -850,9 +851,10 @@ bool TCPHandler::receivePacket()
|
||||
return true;
|
||||
|
||||
case Protocol::Client::Data:
|
||||
case Protocol::Client::Scalar:
|
||||
if (state.empty())
|
||||
receiveUnexpectedData();
|
||||
return receiveData();
|
||||
return receiveData(packet_type == Protocol::Client::Scalar);
|
||||
|
||||
case Protocol::Client::Ping:
|
||||
writeVarUInt(Protocol::Server::Pong, *out);
|
||||
@ -957,39 +959,44 @@ void TCPHandler::receiveUnexpectedQuery()
|
||||
throw NetException("Unexpected packet Query received from client", ErrorCodes::UNEXPECTED_PACKET_FROM_CLIENT);
|
||||
}
|
||||
|
||||
bool TCPHandler::receiveData()
|
||||
bool TCPHandler::receiveData(bool scalar)
|
||||
{
|
||||
initBlockInput();
|
||||
|
||||
/// The name of the temporary table for writing data, default to empty string
|
||||
String external_table_name;
|
||||
readStringBinary(external_table_name, *in);
|
||||
String name;
|
||||
readStringBinary(name, *in);
|
||||
|
||||
/// Read one block from the network and write it down
|
||||
Block block = state.block_in->read();
|
||||
|
||||
if (block)
|
||||
{
|
||||
/// If there is an insert request, then the data should be written directly to `state.io.out`.
|
||||
/// Otherwise, we write the blocks in the temporary `external_table_name` table.
|
||||
if (!state.need_receive_data_for_insert && !state.need_receive_data_for_input)
|
||||
{
|
||||
StoragePtr storage;
|
||||
/// If such a table does not exist, create it.
|
||||
if (!(storage = query_context->tryGetExternalTable(external_table_name)))
|
||||
{
|
||||
NamesAndTypesList columns = block.getNamesAndTypesList();
|
||||
storage = StorageMemory::create("_external", external_table_name, ColumnsDescription{columns}, ConstraintsDescription{});
|
||||
storage->startup();
|
||||
query_context->addExternalTable(external_table_name, storage);
|
||||
}
|
||||
/// The data will be written directly to the table.
|
||||
state.io.out = storage->write(ASTPtr(), *query_context);
|
||||
}
|
||||
if (state.need_receive_data_for_input)
|
||||
state.block_for_input = block;
|
||||
if (scalar)
|
||||
query_context->addScalar(name, block);
|
||||
else
|
||||
state.io.out->write(block);
|
||||
{
|
||||
/// If there is an insert request, then the data should be written directly to `state.io.out`.
|
||||
/// Otherwise, we write the blocks in the temporary `external_table_name` table.
|
||||
if (!state.need_receive_data_for_insert && !state.need_receive_data_for_input)
|
||||
{
|
||||
StoragePtr storage;
|
||||
/// If such a table does not exist, create it.
|
||||
if (!(storage = query_context->tryGetExternalTable(name)))
|
||||
{
|
||||
NamesAndTypesList columns = block.getNamesAndTypesList();
|
||||
storage = StorageMemory::create("_external", name, ColumnsDescription{columns}, ConstraintsDescription{});
|
||||
storage->startup();
|
||||
query_context->addExternalTable(name, storage);
|
||||
}
|
||||
/// The data will be written directly to the table.
|
||||
state.io.out = storage->write(ASTPtr(), *query_context);
|
||||
}
|
||||
if (state.need_receive_data_for_input)
|
||||
state.block_for_input = block;
|
||||
else
|
||||
state.io.out->write(block);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -153,7 +153,7 @@ private:
|
||||
void receiveHello();
|
||||
bool receivePacket();
|
||||
void receiveQuery();
|
||||
bool receiveData();
|
||||
bool receiveData(bool scalar);
|
||||
bool readDataNext(const size_t & poll_interval, const int & receive_timeout);
|
||||
void readData(const Settings & global_settings);
|
||||
std::tuple<size_t, int> getReadTimeouts(const Settings & global_settings);
|
||||
|
@ -180,7 +180,21 @@
|
||||
<port>9000</port>
|
||||
</replica>
|
||||
</shard>
|
||||
</test_cluster_two_shards_localhost>
|
||||
</test_cluster_two_shards_localhost>
|
||||
<test_cluster_two_shards>
|
||||
<shard>
|
||||
<replica>
|
||||
<host>127.0.0.1</host>
|
||||
<port>9000</port>
|
||||
</replica>
|
||||
</shard>
|
||||
<shard>
|
||||
<replica>
|
||||
<host>127.0.0.2</host>
|
||||
<port>9000</port>
|
||||
</replica>
|
||||
</shard>
|
||||
</test_cluster_two_shards>
|
||||
<test_shard_localhost_secure>
|
||||
<shard>
|
||||
<replica>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <Interpreters/SettingsConstraints.h>
|
||||
#include <Access/SettingsConstraints.h>
|
||||
#include <Core/Settings.h>
|
||||
#include <Common/FieldVisitors.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
@ -29,22 +29,118 @@ void SettingsConstraints::clear()
|
||||
}
|
||||
|
||||
|
||||
void SettingsConstraints::setReadOnly(const String & name, bool read_only)
|
||||
void SettingsConstraints::setMinValue(const StringRef & name, const Field & min_value)
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
getConstraintRef(setting_index).min_value = Settings::valueToCorrespondingType(setting_index, min_value);
|
||||
}
|
||||
|
||||
|
||||
Field SettingsConstraints::getMinValue(const StringRef & name) const
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
const auto * ptr = tryGetConstraint(setting_index);
|
||||
if (ptr)
|
||||
return ptr->min_value;
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
void SettingsConstraints::setMaxValue(const StringRef & name, const Field & max_value)
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
getConstraintRef(setting_index).max_value = Settings::valueToCorrespondingType(setting_index, max_value);
|
||||
}
|
||||
|
||||
|
||||
Field SettingsConstraints::getMaxValue(const StringRef & name) const
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
const auto * ptr = tryGetConstraint(setting_index);
|
||||
if (ptr)
|
||||
return ptr->max_value;
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
void SettingsConstraints::setReadOnly(const StringRef & name, bool read_only)
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
getConstraintRef(setting_index).read_only = read_only;
|
||||
}
|
||||
|
||||
void SettingsConstraints::setMinValue(const String & name, const Field & min_value)
|
||||
|
||||
bool SettingsConstraints::isReadOnly(const StringRef & name) const
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
getConstraintRef(setting_index).min_value = Settings::castValueWithoutApplying(setting_index, min_value);
|
||||
const auto * ptr = tryGetConstraint(setting_index);
|
||||
if (ptr)
|
||||
return ptr->read_only;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void SettingsConstraints::setMaxValue(const String & name, const Field & max_value)
|
||||
|
||||
void SettingsConstraints::set(const StringRef & name, const Field & min_value, const Field & max_value, bool read_only)
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
getConstraintRef(setting_index).max_value = Settings::castValueWithoutApplying(setting_index, max_value);
|
||||
auto & ref = getConstraintRef(setting_index);
|
||||
ref.min_value = min_value;
|
||||
ref.max_value = max_value;
|
||||
ref.read_only = read_only;
|
||||
}
|
||||
|
||||
|
||||
void SettingsConstraints::get(const StringRef & name, Field & min_value, Field & max_value, bool & read_only) const
|
||||
{
|
||||
size_t setting_index = Settings::findIndexStrict(name);
|
||||
const auto * ptr = tryGetConstraint(setting_index);
|
||||
if (ptr)
|
||||
{
|
||||
min_value = ptr->min_value;
|
||||
max_value = ptr->max_value;
|
||||
read_only = ptr->read_only;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_value = Field{};
|
||||
max_value = Field{};
|
||||
read_only = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SettingsConstraints::merge(const SettingsConstraints & other)
|
||||
{
|
||||
for (const auto & [setting_index, other_constraint] : other.constraints_by_index)
|
||||
{
|
||||
auto & constraint = constraints_by_index[setting_index];
|
||||
if (!other_constraint.min_value.isNull())
|
||||
constraint.min_value = other_constraint.min_value;
|
||||
if (!other_constraint.max_value.isNull())
|
||||
constraint.max_value = other_constraint.max_value;
|
||||
if (other_constraint.read_only)
|
||||
constraint.read_only = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SettingsConstraints::Infos SettingsConstraints::getInfo() const
|
||||
{
|
||||
Infos result;
|
||||
result.reserve(constraints_by_index.size());
|
||||
for (const auto & [setting_index, constraint] : constraints_by_index)
|
||||
{
|
||||
result.emplace_back();
|
||||
Info & info = result.back();
|
||||
info.name = Settings::getName(setting_index);
|
||||
info.min = constraint.min_value;
|
||||
info.max = constraint.max_value;
|
||||
info.read_only = constraint.read_only;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -55,7 +151,7 @@ void SettingsConstraints::check(const Settings & current_settings, const Setting
|
||||
if (setting_index == Settings::npos)
|
||||
return;
|
||||
|
||||
Field new_value = Settings::castValueWithoutApplying(setting_index, change.value);
|
||||
Field new_value = Settings::valueToCorrespondingType(setting_index, change.value);
|
||||
Field current_value = current_settings.get(setting_index);
|
||||
|
||||
/// Setting isn't checked if value wasn't changed.
|
||||
@ -159,4 +255,15 @@ void SettingsConstraints::loadFromConfig(const String & path_to_constraints, con
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SettingsConstraints::Constraint::operator==(const Constraint & rhs) const
|
||||
{
|
||||
return (read_only == rhs.read_only) && (min_value == rhs.min_value) && (max_value == rhs.max_value);
|
||||
}
|
||||
|
||||
|
||||
bool operator ==(const SettingsConstraints & lhs, const SettingsConstraints & rhs)
|
||||
{
|
||||
return lhs.constraints_by_index == rhs.constraints_by_index;
|
||||
}
|
||||
}
|
@ -58,10 +58,32 @@ public:
|
||||
~SettingsConstraints();
|
||||
|
||||
void clear();
|
||||
bool empty() const { return constraints_by_index.empty(); }
|
||||
|
||||
void setMinValue(const String & name, const Field & min_value);
|
||||
void setMaxValue(const String & name, const Field & max_value);
|
||||
void setReadOnly(const String & name, bool read_only);
|
||||
void setMinValue(const StringRef & name, const Field & min_value);
|
||||
Field getMinValue(const StringRef & name) const;
|
||||
|
||||
void setMaxValue(const StringRef & name, const Field & max_value);
|
||||
Field getMaxValue(const StringRef & name) const;
|
||||
|
||||
void setReadOnly(const StringRef & name, bool read_only);
|
||||
bool isReadOnly(const StringRef & name) const;
|
||||
|
||||
void set(const StringRef & name, const Field & min_value, const Field & max_value, bool read_only);
|
||||
void get(const StringRef & name, Field & min_value, Field & max_value, bool & read_only) const;
|
||||
|
||||
void merge(const SettingsConstraints & other);
|
||||
|
||||
struct Info
|
||||
{
|
||||
StringRef name;
|
||||
Field min;
|
||||
Field max;
|
||||
bool read_only = false;
|
||||
};
|
||||
using Infos = std::vector<Info>;
|
||||
|
||||
Infos getInfo() const;
|
||||
|
||||
void check(const Settings & current_settings, const SettingChange & change) const;
|
||||
void check(const Settings & current_settings, const SettingsChanges & changes) const;
|
||||
@ -74,12 +96,18 @@ public:
|
||||
/// Loads the constraints from configuration file, at "path" prefix in configuration.
|
||||
void loadFromConfig(const String & path, const Poco::Util::AbstractConfiguration & config);
|
||||
|
||||
friend bool operator ==(const SettingsConstraints & lhs, const SettingsConstraints & rhs);
|
||||
friend bool operator !=(const SettingsConstraints & lhs, const SettingsConstraints & rhs) { return !(lhs == rhs); }
|
||||
|
||||
private:
|
||||
struct Constraint
|
||||
{
|
||||
bool read_only = false;
|
||||
Field min_value;
|
||||
Field max_value;
|
||||
|
||||
bool operator ==(const Constraint & rhs) const;
|
||||
bool operator !=(const Constraint & rhs) const { return !(*this == rhs); }
|
||||
};
|
||||
|
||||
Constraint & getConstraintRef(size_t index);
|
@ -31,9 +31,9 @@ struct AggregateFunctionAvgData
|
||||
if constexpr (std::numeric_limits<ResultT>::is_iec559)
|
||||
return static_cast<ResultT>(sum) / count; /// allow division by zero
|
||||
|
||||
if (!count)
|
||||
throw Exception("AggregateFunctionAvg with zero values", ErrorCodes::LOGICAL_ERROR);
|
||||
return static_cast<ResultT>(sum) / count;
|
||||
if (count == 0)
|
||||
return static_cast<ResultT>(0);
|
||||
return static_cast<ResultT>(sum / count);
|
||||
}
|
||||
};
|
||||
|
||||
@ -43,10 +43,10 @@ template <typename T, typename Data>
|
||||
class AggregateFunctionAvg final : public IAggregateFunctionDataHelper<Data, AggregateFunctionAvg<T, Data>>
|
||||
{
|
||||
public:
|
||||
using ResultType = std::conditional_t<IsDecimalNumber<T>, Decimal128, Float64>;
|
||||
using ResultDataType = std::conditional_t<IsDecimalNumber<T>, DataTypeDecimal<Decimal128>, DataTypeNumber<Float64>>;
|
||||
using ResultType = std::conditional_t<IsDecimalNumber<T>, T, Float64>;
|
||||
using ResultDataType = std::conditional_t<IsDecimalNumber<T>, DataTypeDecimal<T>, DataTypeNumber<Float64>>;
|
||||
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
||||
using ColVecResult = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<Decimal128>, ColumnVector<Float64>>;
|
||||
using ColVecResult = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<Float64>>;
|
||||
|
||||
/// ctor for native types
|
||||
AggregateFunctionAvg(const DataTypes & argument_types_)
|
||||
|
@ -64,6 +64,12 @@ public:
|
||||
}
|
||||
|
||||
const char * getHeaderFilePath() const override { return __FILE__; }
|
||||
|
||||
/// Reset the state to specified value. This function is not the part of common interface.
|
||||
void set(AggregateDataPtr place, UInt64 new_count)
|
||||
{
|
||||
data(place).count = new_count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -90,6 +90,10 @@ public:
|
||||
{
|
||||
Data & data_lhs = this->data(place);
|
||||
const Data & data_rhs = this->data(rhs);
|
||||
|
||||
if (!data_rhs.doneFirst)
|
||||
return;
|
||||
|
||||
if (!data_lhs.doneFirst)
|
||||
{
|
||||
data_lhs.doneFirst = true;
|
||||
|
@ -673,15 +673,15 @@ struct AggregateFunctionAnyHeavyData : Data
|
||||
};
|
||||
|
||||
|
||||
template <typename Data, bool AllocatesMemoryInArena>
|
||||
class AggregateFunctionsSingleValue final : public IAggregateFunctionDataHelper<Data, AggregateFunctionsSingleValue<Data, AllocatesMemoryInArena>>
|
||||
template <typename Data, bool use_arena>
|
||||
class AggregateFunctionsSingleValue final : public IAggregateFunctionDataHelper<Data, AggregateFunctionsSingleValue<Data, use_arena>>
|
||||
{
|
||||
private:
|
||||
DataTypePtr & type;
|
||||
|
||||
public:
|
||||
AggregateFunctionsSingleValue(const DataTypePtr & type_)
|
||||
: IAggregateFunctionDataHelper<Data, AggregateFunctionsSingleValue<Data, AllocatesMemoryInArena>>({type_}, {})
|
||||
: IAggregateFunctionDataHelper<Data, AggregateFunctionsSingleValue<Data, use_arena>>({type_}, {})
|
||||
, type(this->argument_types[0])
|
||||
{
|
||||
if (StringRef(Data::name()) == StringRef("min")
|
||||
@ -722,7 +722,7 @@ public:
|
||||
|
||||
bool allocatesMemoryInArena() const override
|
||||
{
|
||||
return AllocatesMemoryInArena;
|
||||
return use_arena;
|
||||
}
|
||||
|
||||
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
|
||||
|
@ -16,11 +16,11 @@ namespace ErrorCodes
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename Value, bool FloatReturn> using FuncQuantile = AggregateFunctionQuantile<Value, QuantileReservoirSampler<Value>, NameQuantile, false, std::conditional_t<FloatReturn, Float64, void>, false>;
|
||||
template <typename Value, bool FloatReturn> using FuncQuantiles = AggregateFunctionQuantile<Value, QuantileReservoirSampler<Value>, NameQuantiles, false, std::conditional_t<FloatReturn, Float64, void>, true>;
|
||||
template <typename Value, bool float_return> using FuncQuantile = AggregateFunctionQuantile<Value, QuantileReservoirSampler<Value>, NameQuantile, false, std::conditional_t<float_return, Float64, void>, false>;
|
||||
template <typename Value, bool float_return> using FuncQuantiles = AggregateFunctionQuantile<Value, QuantileReservoirSampler<Value>, NameQuantiles, false, std::conditional_t<float_return, Float64, void>, true>;
|
||||
|
||||
template <typename Value, bool FloatReturn> using FuncQuantileDeterministic = AggregateFunctionQuantile<Value, QuantileReservoirSamplerDeterministic<Value>, NameQuantileDeterministic, true, std::conditional_t<FloatReturn, Float64, void>, false>;
|
||||
template <typename Value, bool FloatReturn> using FuncQuantilesDeterministic = AggregateFunctionQuantile<Value, QuantileReservoirSamplerDeterministic<Value>, NameQuantilesDeterministic, true, std::conditional_t<FloatReturn, Float64, void>, true>;
|
||||
template <typename Value, bool float_return> using FuncQuantileDeterministic = AggregateFunctionQuantile<Value, QuantileReservoirSamplerDeterministic<Value>, NameQuantileDeterministic, true, std::conditional_t<float_return, Float64, void>, false>;
|
||||
template <typename Value, bool float_return> using FuncQuantilesDeterministic = AggregateFunctionQuantile<Value, QuantileReservoirSamplerDeterministic<Value>, NameQuantilesDeterministic, true, std::conditional_t<float_return, Float64, void>, true>;
|
||||
|
||||
template <typename Value, bool _> using FuncQuantileExact = AggregateFunctionQuantile<Value, QuantileExact<Value>, NameQuantileExact, false, void, false>;
|
||||
template <typename Value, bool _> using FuncQuantilesExact = AggregateFunctionQuantile<Value, QuantileExact<Value>, NameQuantilesExact, false, void, true>;
|
||||
@ -40,11 +40,11 @@ template <typename Value, bool _> using FuncQuantilesTiming = AggregateFunctionQ
|
||||
template <typename Value, bool _> using FuncQuantileTimingWeighted = AggregateFunctionQuantile<Value, QuantileTiming<Value>, NameQuantileTimingWeighted, true, Float32, false>;
|
||||
template <typename Value, bool _> using FuncQuantilesTimingWeighted = AggregateFunctionQuantile<Value, QuantileTiming<Value>, NameQuantilesTimingWeighted, true, Float32, true>;
|
||||
|
||||
template <typename Value, bool FloatReturn> using FuncQuantileTDigest = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantileTDigest, false, std::conditional_t<FloatReturn, Float32, void>, false>;
|
||||
template <typename Value, bool FloatReturn> using FuncQuantilesTDigest = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantilesTDigest, false, std::conditional_t<FloatReturn, Float32, void>, true>;
|
||||
template <typename Value, bool float_return> using FuncQuantileTDigest = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantileTDigest, false, std::conditional_t<float_return, Float32, void>, false>;
|
||||
template <typename Value, bool float_return> using FuncQuantilesTDigest = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantilesTDigest, false, std::conditional_t<float_return, Float32, void>, true>;
|
||||
|
||||
template <typename Value, bool FloatReturn> using FuncQuantileTDigestWeighted = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantileTDigestWeighted, true, std::conditional_t<FloatReturn, Float32, void>, false>;
|
||||
template <typename Value, bool FloatReturn> using FuncQuantilesTDigestWeighted = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantilesTDigestWeighted, true, std::conditional_t<FloatReturn, Float32, void>, true>;
|
||||
template <typename Value, bool float_return> using FuncQuantileTDigestWeighted = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantileTDigestWeighted, true, std::conditional_t<float_return, Float32, void>, false>;
|
||||
template <typename Value, bool float_return> using FuncQuantilesTDigestWeighted = AggregateFunctionQuantile<Value, QuantileTDigest<Value>, NameQuantilesTDigestWeighted, true, std::conditional_t<float_return, Float32, void>, true>;
|
||||
|
||||
|
||||
template <template <typename, bool> class Function>
|
||||
|
@ -31,7 +31,7 @@ namespace ReservoirSamplerOnEmpty
|
||||
};
|
||||
}
|
||||
|
||||
template <typename ResultType, bool IsFloatingPoint>
|
||||
template <typename ResultType, bool is_float>
|
||||
struct NanLikeValueConstructor
|
||||
{
|
||||
static ResultType getValue()
|
||||
@ -109,8 +109,11 @@ public:
|
||||
double quantileInterpolated(double level)
|
||||
{
|
||||
if (samples.empty())
|
||||
{
|
||||
if (DB::IsDecimalNumber<T>)
|
||||
return 0;
|
||||
return onEmpty<double>();
|
||||
|
||||
}
|
||||
sortIfNeeded();
|
||||
|
||||
double index = std::max(0., std::min(samples.size() - 1., level * (samples.size() - 1)));
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
namespace CurrentMetrics
|
||||
{
|
||||
extern const Metric SendScalars;
|
||||
extern const Metric SendExternalTables;
|
||||
}
|
||||
|
||||
@ -441,7 +442,7 @@ void Connection::sendCancel()
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendData(const Block & block, const String & name)
|
||||
void Connection::sendData(const Block & block, const String & name, bool scalar)
|
||||
{
|
||||
//LOG_TRACE(log_wrapper.get(), "Sending data");
|
||||
|
||||
@ -455,7 +456,10 @@ void Connection::sendData(const Block & block, const String & name)
|
||||
block_out = std::make_shared<NativeBlockOutputStream>(*maybe_compressed_out, server_revision, block.cloneEmpty());
|
||||
}
|
||||
|
||||
writeVarUInt(Protocol::Client::Data, *out);
|
||||
if (scalar)
|
||||
writeVarUInt(Protocol::Client::Scalar, *out);
|
||||
else
|
||||
writeVarUInt(Protocol::Client::Data, *out);
|
||||
writeStringBinary(name, *out);
|
||||
|
||||
size_t prev_bytes = out->count();
|
||||
@ -484,6 +488,44 @@ void Connection::sendPreparedData(ReadBuffer & input, size_t size, const String
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendScalarsData(Scalars & data)
|
||||
{
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
Stopwatch watch;
|
||||
size_t out_bytes = out ? out->count() : 0;
|
||||
size_t maybe_compressed_out_bytes = maybe_compressed_out ? maybe_compressed_out->count() : 0;
|
||||
size_t rows = 0;
|
||||
|
||||
CurrentMetrics::Increment metric_increment{CurrentMetrics::SendScalars};
|
||||
|
||||
for (auto & elem : data)
|
||||
{
|
||||
rows += elem.second.rows();
|
||||
sendData(elem.second, elem.first, true /* scalar */);
|
||||
}
|
||||
|
||||
out_bytes = out->count() - out_bytes;
|
||||
maybe_compressed_out_bytes = maybe_compressed_out->count() - maybe_compressed_out_bytes;
|
||||
double elapsed = watch.elapsedSeconds();
|
||||
|
||||
std::stringstream msg;
|
||||
msg << std::fixed << std::setprecision(3);
|
||||
msg << "Sent data for " << data.size() << " scalars, total " << rows << " rows in " << elapsed << " sec., "
|
||||
<< static_cast<size_t>(rows / watch.elapsedSeconds()) << " rows/sec., "
|
||||
<< maybe_compressed_out_bytes / 1048576.0 << " MiB (" << maybe_compressed_out_bytes / 1048576.0 / watch.elapsedSeconds() << " MiB/sec.)";
|
||||
|
||||
if (compression == Protocol::Compression::Enable)
|
||||
msg << ", compressed " << static_cast<double>(maybe_compressed_out_bytes) / out_bytes << " times to "
|
||||
<< out_bytes / 1048576.0 << " MiB (" << out_bytes / 1048576.0 / watch.elapsedSeconds() << " MiB/sec.)";
|
||||
else
|
||||
msg << ", no compression.";
|
||||
|
||||
LOG_DEBUG(log_wrapper.get(), msg.rdbuf());
|
||||
}
|
||||
|
||||
|
||||
void Connection::sendExternalTablesData(ExternalTablesData & data)
|
||||
{
|
||||
if (data.empty())
|
||||
|
@ -133,7 +133,9 @@ public:
|
||||
|
||||
void sendCancel();
|
||||
/// Send block of data; if name is specified, server will write it to external (temporary) table of that name.
|
||||
void sendData(const Block & block, const String & name = "");
|
||||
void sendData(const Block & block, const String & name = "", bool scalar = false);
|
||||
/// Send all scalars.
|
||||
void sendScalarsData(Scalars & data);
|
||||
/// Send all contents of external (temporary) tables.
|
||||
void sendExternalTablesData(ExternalTablesData & data);
|
||||
|
||||
|
@ -51,6 +51,21 @@ MultiplexedConnections::MultiplexedConnections(
|
||||
active_connection_count = connections.size();
|
||||
}
|
||||
|
||||
void MultiplexedConnections::sendScalarsData(Scalars & data)
|
||||
{
|
||||
std::lock_guard lock(cancel_mutex);
|
||||
|
||||
if (!sent_query)
|
||||
throw Exception("Cannot send scalars data: query not yet sent.", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
for (ReplicaState & state : replica_states)
|
||||
{
|
||||
Connection * connection = state.connection;
|
||||
if (connection != nullptr)
|
||||
connection->sendScalarsData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplexedConnections::sendExternalTablesData(std::vector<ExternalTablesData> & data)
|
||||
{
|
||||
std::lock_guard lock(cancel_mutex);
|
||||
|
@ -27,6 +27,8 @@ public:
|
||||
std::vector<IConnectionPool::Entry> && connections,
|
||||
const Settings & settings_, const ThrottlerPtr & throttler_);
|
||||
|
||||
/// Send all scalars to replicas.
|
||||
void sendScalarsData(Scalars & data);
|
||||
/// Send all content of external tables to replicas.
|
||||
void sendExternalTablesData(std::vector<ExternalTablesData> & data);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Columns/IColumnDummy.h>
|
||||
#include <Core/Field.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -28,6 +29,9 @@ public:
|
||||
|
||||
ConstSetPtr getData() const { return data; }
|
||||
|
||||
// Used only for debugging, making it DUMPABLE
|
||||
Field operator[](size_t) const override { return {}; }
|
||||
|
||||
private:
|
||||
ConstSetPtr data;
|
||||
};
|
||||
|
@ -112,7 +112,7 @@ void ColumnVector<T>::getPermutation(bool reverse, size_t limit, int nan_directi
|
||||
else
|
||||
{
|
||||
/// A case for radix sort
|
||||
if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, UInt128>)
|
||||
if constexpr (is_arithmetic_v<T> && !std::is_same_v<T, UInt128>)
|
||||
{
|
||||
/// Thresholds on size. Lower threshold is arbitrary. Upper threshold is chosen by the type for histogram counters.
|
||||
if (s >= 256 && s <= std::numeric_limits<UInt32>::max())
|
||||
|
@ -21,6 +21,7 @@
|
||||
M(OpenFileForWrite, "Number of files open for writing") \
|
||||
M(Read, "Number of read (read, pread, io_getevents, etc.) syscalls in fly") \
|
||||
M(Write, "Number of write (write, pwrite, io_getevents, etc.) syscalls in fly") \
|
||||
M(SendScalars, "Number of connections that are sending data for scalars to remote servers.") \
|
||||
M(SendExternalTables, "Number of connections that are sending data for external tables to remote servers. External tables are used to implement GLOBAL IN and GLOBAL JOIN operators with distributed subqueries.") \
|
||||
M(QueryThread, "Number of query processing threads") \
|
||||
M(ReadonlyReplica, "Number of Replicated tables that are currently in readonly state due to re-initialization after ZooKeeper session loss or due to startup without ZooKeeper configured.") \
|
||||
|
@ -155,7 +155,7 @@ namespace ErrorCodes
|
||||
extern const int NOT_FOUND_FUNCTION_ELEMENT_FOR_AGGREGATE = 147;
|
||||
extern const int NOT_FOUND_RELATION_ELEMENT_FOR_CONDITION = 148;
|
||||
extern const int NOT_FOUND_RHS_ELEMENT_FOR_CONDITION = 149;
|
||||
extern const int NO_ATTRIBUTES_LISTED = 150;
|
||||
extern const int EMPTY_LIST_OF_ATTRIBUTES_PASSED = 150;
|
||||
extern const int INDEX_OF_COLUMN_IN_SORT_CLAUSE_IS_OUT_OF_RANGE = 151;
|
||||
extern const int UNKNOWN_DIRECTION_OF_SORTING = 152;
|
||||
extern const int ILLEGAL_DIVISION = 153;
|
||||
@ -361,7 +361,7 @@ namespace ErrorCodes
|
||||
extern const int PART_IS_TEMPORARILY_LOCKED = 384;
|
||||
extern const int MULTIPLE_STREAMS_REQUIRED = 385;
|
||||
extern const int NO_COMMON_TYPE = 386;
|
||||
extern const int EXTERNAL_LOADABLE_ALREADY_EXISTS = 387;
|
||||
extern const int DICTIONARY_ALREADY_EXISTS = 387;
|
||||
extern const int CANNOT_ASSIGN_OPTIMIZE = 388;
|
||||
extern const int INSERT_WAS_DEDUPLICATED = 389;
|
||||
extern const int CANNOT_GET_CREATE_TABLE_QUERY = 390;
|
||||
@ -459,6 +459,11 @@ namespace ErrorCodes
|
||||
extern const int DICTIONARY_ACCESS_DENIED = 482;
|
||||
extern const int TOO_MANY_REDIRECTS = 483;
|
||||
extern const int INTERNAL_REDIS_ERROR = 484;
|
||||
extern const int SCALAR_ALREADY_EXISTS = 485;
|
||||
extern const int UNKNOWN_SCALAR = 486;
|
||||
extern const int CANNOT_GET_CREATE_DICTIONARY_QUERY = 487;
|
||||
extern const int UNKNOWN_DICTIONARY = 488;
|
||||
extern const int INCORRECT_DICTIONARY_DEFINITION = 489;
|
||||
|
||||
extern const int KEEPER_EXCEPTION = 999;
|
||||
extern const int POCO_EXCEPTION = 1000;
|
||||
|
@ -76,7 +76,7 @@ template <typename T, typename Enable = void>
|
||||
struct DefaultHash;
|
||||
|
||||
template <typename T>
|
||||
struct DefaultHash<T, std::enable_if_t<std::is_arithmetic_v<T>>>
|
||||
struct DefaultHash<T, std::enable_if_t<is_arithmetic_v<T>>>
|
||||
{
|
||||
size_t operator() (T key) const
|
||||
{
|
||||
|
@ -165,12 +165,10 @@ struct RadixSortIntTraits
|
||||
|
||||
|
||||
template <typename T>
|
||||
using RadixSortNumTraits =
|
||||
std::conditional_t<std::is_integral_v<T>,
|
||||
std::conditional_t<std::is_unsigned_v<T>,
|
||||
RadixSortUIntTraits<T>,
|
||||
RadixSortIntTraits<T>>,
|
||||
RadixSortFloatTraits<T>>;
|
||||
using RadixSortNumTraits = std::conditional_t<
|
||||
is_integral_v<T>,
|
||||
std::conditional_t<is_unsigned_v<T>, RadixSortUIntTraits<T>, RadixSortIntTraits<T>>,
|
||||
RadixSortFloatTraits<T>>;
|
||||
|
||||
|
||||
template <typename Traits>
|
||||
|
@ -10,6 +10,9 @@ struct SettingChange
|
||||
{
|
||||
String name;
|
||||
Field value;
|
||||
|
||||
friend bool operator ==(const SettingChange & lhs, const SettingChange & rhs) { return (lhs.name == rhs.name) && (lhs.value == rhs.value); }
|
||||
friend bool operator !=(const SettingChange & lhs, const SettingChange & rhs) { return !(lhs == rhs); }
|
||||
};
|
||||
|
||||
using SettingsChanges = std::vector<SettingChange>;
|
||||
|
@ -30,7 +30,7 @@ std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext
|
||||
else
|
||||
error << "Address: " << info.si_addr;
|
||||
|
||||
#if defined(__x86_64__) && !defined(__FreeBSD__) && !defined(__APPLE__)
|
||||
#if defined(__x86_64__) && !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__arm__)
|
||||
auto err_mask = context.uc_mcontext.gregs[REG_ERR];
|
||||
if ((err_mask & 0x02))
|
||||
error << " Access: write.";
|
||||
|
@ -182,18 +182,8 @@ struct UInt256HashCRC32
|
||||
struct UInt256HashCRC32 : public UInt256Hash {};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Overload hash for type casting
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<DB::UInt128>
|
||||
{
|
||||
size_t operator()(const DB::UInt128 & u) const
|
||||
{
|
||||
return CityHash_v1_0_2::Hash128to64({u.low, u.high});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <> struct is_signed<DB::UInt128>
|
||||
{
|
||||
@ -215,4 +205,16 @@ template <> struct is_arithmetic<DB::UInt128>
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
/// Overload hash for type casting
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<DB::UInt128>
|
||||
{
|
||||
size_t operator()(const DB::UInt128 & u) const
|
||||
{
|
||||
return CityHash_v1_0_2::Hash128to64({u.low, u.high});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ protected:
|
||||
public:
|
||||
using Configuration = Poco::Util::AbstractConfiguration;
|
||||
|
||||
Context & context;
|
||||
const Context & context;
|
||||
const Configuration & config;
|
||||
|
||||
static constexpr inline auto DEFAULT_HOST = "localhost";
|
||||
@ -79,7 +79,7 @@ public:
|
||||
static constexpr inline auto IDENTIFIER_QUOTE_HANDLER = "/identifier_quote";
|
||||
static constexpr inline auto PING_OK_ANSWER = "Ok.";
|
||||
|
||||
XDBCBridgeHelper(Context & global_context_, const Poco::Timespan & http_timeout_, const std::string & connection_string_)
|
||||
XDBCBridgeHelper(const Context & global_context_, const Poco::Timespan & http_timeout_, const std::string & connection_string_)
|
||||
: http_timeout(http_timeout_), connection_string(connection_string_), context(global_context_), config(context.getConfigRef())
|
||||
{
|
||||
size_t bridge_port = config.getUInt(BridgeHelperMixin::configPrefix() + ".port", DEFAULT_PORT);
|
||||
|
@ -31,7 +31,7 @@ void setAffinity()
|
||||
|
||||
static inline ALWAYS_INLINE UInt64 rdtsc()
|
||||
{
|
||||
#if __x86_64__
|
||||
#if defined(__x86_64__)
|
||||
UInt32 a, d;
|
||||
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
|
||||
return static_cast<UInt64>(a) | (static_cast<UInt64>(d) << 32);
|
||||
@ -109,7 +109,7 @@ static inline size_t murmurMix(UInt64 x)
|
||||
}
|
||||
|
||||
|
||||
#if __x86_64__
|
||||
#if defined(__x86_64__)
|
||||
static inline size_t crc32Hash(UInt64 x)
|
||||
{
|
||||
UInt64 crc = -1ULL;
|
||||
@ -309,7 +309,7 @@ int main(int argc, char ** argv)
|
||||
if (!method || method == 8) test<mulShift> (n, data.data(), "7: mulShift");
|
||||
if (!method || method == 9) test<tabulation>(n, data.data(), "8: tabulation");
|
||||
|
||||
#if __x86_64__
|
||||
#if defined(__x86_64__)
|
||||
if (!method || method == 10) test<crc32Hash> (n, data.data(), "9: crc32");
|
||||
#endif
|
||||
|
||||
|
@ -109,7 +109,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest)
|
||||
{
|
||||
// Since only unsinged int has granted 2-compliment overflow handling, we are doing math here on unsigned types.
|
||||
// To simplify and booletproof code, we operate enforce ValueType to be unsigned too.
|
||||
static_assert(std::is_unsigned_v<ValueType>, "ValueType must be unsigned.");
|
||||
static_assert(is_unsigned_v<ValueType>, "ValueType must be unsigned.");
|
||||
using UnsignedDeltaType = ValueType;
|
||||
|
||||
// We use signed delta type to turn huge unsigned values into smaller signed:
|
||||
@ -189,7 +189,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest)
|
||||
template <typename ValueType>
|
||||
void decompressDataForType(const char * source, UInt32 source_size, char * dest)
|
||||
{
|
||||
static_assert(std::is_unsigned_v<ValueType>, "ValueType must be unsigned.");
|
||||
static_assert(is_unsigned_v<ValueType>, "ValueType must be unsigned.");
|
||||
using UnsignedDeltaType = ValueType;
|
||||
using SignedDeltaType = typename std::make_signed<UnsignedDeltaType>::type;
|
||||
|
||||
|
@ -262,10 +262,10 @@ void reverseTranspose(const char * src, T * buf, UInt32 num_bits, UInt32 tail =
|
||||
reverseTransposeBytes(matrix, col, buf[col]);
|
||||
}
|
||||
|
||||
template <typename T, typename MinMaxT = std::conditional_t<std::is_signed_v<T>, Int64, UInt64>>
|
||||
template <typename T, typename MinMaxT = std::conditional_t<is_signed_v<T>, Int64, UInt64>>
|
||||
void restoreUpperBits(T * buf, T upper_min, T upper_max [[maybe_unused]], T sign_bit [[maybe_unused]], UInt32 tail = 64)
|
||||
{
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
if constexpr (is_signed_v<T>)
|
||||
{
|
||||
/// Restore some data as negatives and others as positives
|
||||
if (sign_bit)
|
||||
@ -334,7 +334,7 @@ using Variant = CompressionCodecT64::Variant;
|
||||
template <typename T, bool full>
|
||||
UInt32 compressData(const char * src, UInt32 bytes_size, char * dst)
|
||||
{
|
||||
using MinMaxType = std::conditional_t<std::is_signed_v<T>, Int64, UInt64>;
|
||||
using MinMaxType = std::conditional_t<is_signed_v<T>, Int64, UInt64>;
|
||||
|
||||
static constexpr const UInt32 matrix_size = 64;
|
||||
static constexpr const UInt32 header_size = 2 * sizeof(UInt64);
|
||||
@ -389,7 +389,7 @@ UInt32 compressData(const char * src, UInt32 bytes_size, char * dst)
|
||||
template <typename T, bool full>
|
||||
void decompressData(const char * src, UInt32 bytes_size, char * dst, UInt32 uncompressed_size)
|
||||
{
|
||||
using MinMaxType = std::conditional_t<std::is_signed_v<T>, Int64, UInt64>;
|
||||
using MinMaxType = std::conditional_t<is_signed_v<T>, Int64, UInt64>;
|
||||
|
||||
static constexpr const UInt32 matrix_size = 64;
|
||||
static constexpr const UInt32 header_size = 2 * sizeof(UInt64);
|
||||
@ -441,7 +441,7 @@ void decompressData(const char * src, UInt32 bytes_size, char * dst, UInt32 unco
|
||||
if (num_bits < 64)
|
||||
upper_min = UInt64(min) >> num_bits << num_bits;
|
||||
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
if constexpr (is_signed_v<T>)
|
||||
{
|
||||
if (min < 0 && max >= 0 && num_bits < 64)
|
||||
{
|
||||
|
@ -441,7 +441,7 @@ auto SequentialGenerator = [](auto stride = 1)
|
||||
template <typename T>
|
||||
using uniform_distribution =
|
||||
typename std::conditional_t<std::is_floating_point_v<T>, std::uniform_real_distribution<T>,
|
||||
typename std::conditional_t<std::is_integral_v<T>, std::uniform_int_distribution<T>, void>>;
|
||||
typename std::conditional_t<is_integral_v<T>, std::uniform_int_distribution<T>, void>>;
|
||||
|
||||
|
||||
template <typename T = Int32>
|
||||
|
@ -35,10 +35,10 @@ using DB::UInt64;
|
||||
// Case 1. Is pair of floats or pair of ints or pair of uints
|
||||
template <typename A, typename B>
|
||||
constexpr bool is_safe_conversion = (std::is_floating_point_v<A> && std::is_floating_point_v<B>)
|
||||
|| (std::is_integral_v<A> && std::is_integral_v<B> && !(std::is_signed_v<A> ^ std::is_signed_v<B>))
|
||||
|| (is_integral_v<A> && is_integral_v<B> && !(is_signed_v<A> ^ is_signed_v<B>))
|
||||
|| (std::is_same_v<A, DB::Int128> && std::is_same_v<B, DB::Int128>)
|
||||
|| (std::is_integral_v<A> && std::is_same_v<B, DB::Int128>)
|
||||
|| (std::is_same_v<A, DB::Int128> && std::is_integral_v<B>);
|
||||
|| (is_integral_v<A> && std::is_same_v<B, DB::Int128>)
|
||||
|| (std::is_same_v<A, DB::Int128> && is_integral_v<B>);
|
||||
template <typename A, typename B>
|
||||
using bool_if_safe_conversion = std::enable_if_t<is_safe_conversion<A, B>, bool>;
|
||||
template <typename A, typename B>
|
||||
@ -47,8 +47,8 @@ using bool_if_not_safe_conversion = std::enable_if_t<!is_safe_conversion<A, B>,
|
||||
|
||||
/// Case 2. Are params IntXX and UIntYY ?
|
||||
template <typename TInt, typename TUInt>
|
||||
constexpr bool is_any_int_vs_uint = std::is_integral_v<TInt> && std::is_integral_v<TUInt> &&
|
||||
std::is_signed_v<TInt> && std::is_unsigned_v<TUInt>;
|
||||
constexpr bool is_any_int_vs_uint
|
||||
= is_integral_v<TInt> && is_integral_v<TUInt> && is_signed_v<TInt> && is_unsigned_v<TUInt>;
|
||||
|
||||
|
||||
// Case 2a. Are params IntXX and UIntYY and sizeof(IntXX) >= sizeof(UIntYY) (in such case will use accurate compare)
|
||||
@ -117,9 +117,8 @@ inline bool_if_gt_int_vs_uint<TInt, TUInt> equalsOpTmpl(TUInt a, TInt b)
|
||||
|
||||
// Case 3a. Comparison via conversion to double.
|
||||
template <typename TAInt, typename TAFloat>
|
||||
using bool_if_double_can_be_used = std::enable_if_t<
|
||||
std::is_integral_v<TAInt> && (sizeof(TAInt) <= 4) && std::is_floating_point_v<TAFloat>,
|
||||
bool>;
|
||||
using bool_if_double_can_be_used
|
||||
= std::enable_if_t<is_integral_v<TAInt> && (sizeof(TAInt) <= 4) && std::is_floating_point_v<TAFloat>, bool>;
|
||||
|
||||
template <typename TAInt, typename TAFloat>
|
||||
inline bool_if_double_can_be_used<TAInt, TAFloat> greaterOpTmpl(TAInt a, TAFloat b)
|
||||
|
@ -233,9 +233,9 @@ private:
|
||||
overflow |= (A(x) != a);
|
||||
if constexpr (sizeof(B) > sizeof(CompareInt))
|
||||
overflow |= (B(y) != b);
|
||||
if constexpr (std::is_unsigned_v<A>)
|
||||
if constexpr (is_unsigned_v<A>)
|
||||
overflow |= (x < 0);
|
||||
if constexpr (std::is_unsigned_v<B>)
|
||||
if constexpr (is_unsigned_v<B>)
|
||||
overflow |= (y < 0);
|
||||
|
||||
if constexpr (scale_left)
|
||||
|
@ -11,6 +11,12 @@ class DateLUTImpl;
|
||||
namespace DB
|
||||
{
|
||||
|
||||
static constexpr size_t minDecimalPrecision() { return 1; }
|
||||
template <typename T> static constexpr size_t maxDecimalPrecision() { return 0; }
|
||||
template <> constexpr size_t maxDecimalPrecision<Decimal32>() { return 9; }
|
||||
template <> constexpr size_t maxDecimalPrecision<Decimal64>() { return 18; }
|
||||
template <> constexpr size_t maxDecimalPrecision<Decimal128>() { return 38; }
|
||||
|
||||
template <typename T> T decimalScaleMultiplier(UInt32 scale);
|
||||
template <> inline Int32 decimalScaleMultiplier<Int32>(UInt32 scale) { return common::exp10_i32(scale); }
|
||||
template <> inline Int64 decimalScaleMultiplier<Int64>(UInt32 scale) { return common::exp10_i64(scale); }
|
||||
|
@ -656,7 +656,7 @@ template <> struct TypeName<AggregateFunctionStateData> { static std::string get
|
||||
/// char may be signed or unsigned, and behave identically to signed char or unsigned char,
|
||||
/// but they are always three different types.
|
||||
/// signedness of char is different in Linux on x86 and Linux on ARM.
|
||||
template <> struct NearestFieldTypeImpl<char> { using Type = std::conditional_t<std::is_signed_v<char>, Int64, UInt64>; };
|
||||
template <> struct NearestFieldTypeImpl<char> { using Type = std::conditional_t<is_signed_v<char>, Int64, UInt64>; };
|
||||
template <> struct NearestFieldTypeImpl<signed char> { using Type = Int64; };
|
||||
template <> struct NearestFieldTypeImpl<unsigned char> { using Type = UInt64; };
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
#include "MySQLProtocol.h"
|
||||
|
||||
#if USE_SSL
|
||||
|
||||
#include <IO/WriteBuffer.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
@ -104,5 +101,3 @@ size_t getLengthEncodedStringSize(const String & s)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // USE_SSL
|
||||
|
@ -1,12 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "config_core.h"
|
||||
|
||||
#if USE_SSL
|
||||
|
||||
#include <ext/scope_guard.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <Common/MemoryTracker.h>
|
||||
@ -27,6 +20,11 @@
|
||||
#include <Poco/Net/StreamSocket.h>
|
||||
#include <Poco/RandomStream.h>
|
||||
#include <Poco/SHA1Engine.h>
|
||||
#include "config_core.h"
|
||||
#if USE_SSL
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#endif
|
||||
|
||||
/// Implementation of MySQL wire protocol.
|
||||
/// Works only on little-endian architecture.
|
||||
@ -941,6 +939,7 @@ private:
|
||||
String scramble;
|
||||
};
|
||||
|
||||
#if USE_SSL
|
||||
/// Caching SHA2 plugin is not used because it would be possible to authenticate knowing hash from users.xml.
|
||||
/// https://dev.mysql.com/doc/internals/en/sha256.html
|
||||
class Sha256Password : public IPlugin
|
||||
@ -1001,7 +1000,6 @@ public:
|
||||
if (auth_response == "\1")
|
||||
{
|
||||
LOG_TRACE(log, "Client requests public key.");
|
||||
|
||||
BIO * mem = BIO_new(BIO_s_mem());
|
||||
SCOPE_EXIT(BIO_free(mem));
|
||||
if (PEM_write_bio_RSA_PUBKEY(mem, &public_key) != 1)
|
||||
@ -1074,10 +1072,9 @@ private:
|
||||
Logger * log;
|
||||
String scramble;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_SSL
|
||||
|
@ -112,7 +112,8 @@ namespace Protocol
|
||||
Cancel = 3, /// Cancel the query execution.
|
||||
Ping = 4, /// Check that connection to the server is alive.
|
||||
TablesStatusRequest = 5, /// Check status of tables on the server.
|
||||
KeepAlive = 6 /// Keep the connection alive
|
||||
KeepAlive = 6, /// Keep the connection alive
|
||||
Scalar = 7 /// A block of data (compressed or not).
|
||||
};
|
||||
|
||||
inline const char * toString(UInt64 packet)
|
||||
|
@ -379,6 +379,9 @@ struct Settings : public SettingsCollection<Settings>
|
||||
M(SettingUInt64, max_live_view_insert_blocks_before_refresh, 64, "Limit maximum number of inserted blocks after which mergeable blocks are dropped and query is re-executed.") \
|
||||
M(SettingUInt64, min_free_disk_space_for_temporary_data, 0, "The minimum disk space to keep while writing temporary data used in external sorting and aggregation.") \
|
||||
\
|
||||
M(SettingBool, enable_scalar_subquery_optimization, true, "If it is set to true, prevent scalar subqueries from (de)serializing large scalar values and possibly avoid running the same subquery more than once.") \
|
||||
M(SettingBool, optimize_trivial_count_query, true, "Process trivial 'SELECT count() FROM table' query from metadata.") \
|
||||
\
|
||||
/** Obsolete settings that do nothing but left for compatibility reasons. Remove each one after half a year of obsolescence. */ \
|
||||
\
|
||||
M(SettingBool, allow_experimental_low_cardinality_type, true, "Obsolete setting, does nothing. Will be removed after 2019-08-13") \
|
||||
|
@ -25,15 +25,27 @@ void SettingsCollection<Derived>::reference::setValue(const Field & value)
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
Field SettingsCollection<Derived>::castValueWithoutApplying(size_t index, const Field & value)
|
||||
String SettingsCollection<Derived>::valueToString(size_t index, const Field & value)
|
||||
{
|
||||
return members()[index].cast_value_without_applying(value);
|
||||
return members()[index].value_to_string(value);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
Field SettingsCollection<Derived>::castValueWithoutApplying(const String & name, const Field & value)
|
||||
String SettingsCollection<Derived>::valueToString(const StringRef & name, const Field & value)
|
||||
{
|
||||
return members().findStrict(name)->cast_value_without_applying(value);
|
||||
return members().findStrict(name)->value_to_string(value);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
Field SettingsCollection<Derived>::valueToCorrespondingType(size_t index, const Field & value)
|
||||
{
|
||||
return members()[index].value_to_corresponding_type(value);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
Field SettingsCollection<Derived>::valueToCorrespondingType(const StringRef & name, const Field & value)
|
||||
{
|
||||
return members().findStrict(name)->value_to_corresponding_type(value);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
@ -43,7 +55,7 @@ void SettingsCollection<Derived>::set(size_t index, const Field & value)
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void SettingsCollection<Derived>::set(const String & name, const Field & value)
|
||||
void SettingsCollection<Derived>::set(const StringRef & name, const Field & value)
|
||||
{
|
||||
(*this)[name].setValue(value);
|
||||
}
|
||||
@ -55,13 +67,13 @@ Field SettingsCollection<Derived>::get(size_t index) const
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
Field SettingsCollection<Derived>::get(const String & name) const
|
||||
Field SettingsCollection<Derived>::get(const StringRef & name) const
|
||||
{
|
||||
return (*this)[name].getValue();
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
bool SettingsCollection<Derived>::tryGet(const String & name, Field & value) const
|
||||
bool SettingsCollection<Derived>::tryGet(const StringRef & name, Field & value) const
|
||||
{
|
||||
auto it = find(name);
|
||||
if (it == end())
|
||||
@ -71,7 +83,7 @@ bool SettingsCollection<Derived>::tryGet(const String & name, Field & value) con
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
bool SettingsCollection<Derived>::tryGet(const String & name, String & value) const
|
||||
bool SettingsCollection<Derived>::tryGet(const StringRef & name, String & value) const
|
||||
{
|
||||
auto it = find(name);
|
||||
if (it == end())
|
||||
@ -85,8 +97,8 @@ bool SettingsCollection<Derived>::operator ==(const Derived & rhs) const
|
||||
{
|
||||
for (const auto & member : members())
|
||||
{
|
||||
bool left_changed = member.isChanged(castToDerived());
|
||||
bool right_changed = member.isChanged(rhs);
|
||||
bool left_changed = member.is_changed(castToDerived());
|
||||
bool right_changed = member.is_changed(rhs);
|
||||
if (left_changed || right_changed)
|
||||
{
|
||||
if (left_changed != right_changed)
|
||||
@ -105,7 +117,7 @@ SettingsChanges SettingsCollection<Derived>::changes() const
|
||||
SettingsChanges found_changes;
|
||||
for (const auto & member : members())
|
||||
{
|
||||
if (member.isChanged(castToDerived()))
|
||||
if (member.is_changed(castToDerived()))
|
||||
found_changes.push_back({member.name.toString(), member.get_field(castToDerived())});
|
||||
}
|
||||
return found_changes;
|
||||
@ -130,7 +142,7 @@ template <class Derived>
|
||||
void SettingsCollection<Derived>::copyChangesFrom(const Derived & src)
|
||||
{
|
||||
for (const auto & member : members())
|
||||
if (member.isChanged(src))
|
||||
if (member.is_changed(src))
|
||||
member.set_field(castToDerived(), member.get_field(src));
|
||||
}
|
||||
|
||||
|
@ -92,9 +92,9 @@ void SettingNumber<bool>::set(const String & x)
|
||||
template <typename Type>
|
||||
void SettingNumber<Type>::serialize(WriteBuffer & buf) const
|
||||
{
|
||||
if constexpr (std::is_integral_v<Type> && std::is_unsigned_v<Type>)
|
||||
if constexpr (is_integral_v<Type> && is_unsigned_v<Type>)
|
||||
writeVarUInt(static_cast<UInt64>(value), buf);
|
||||
else if constexpr (std::is_integral_v<Type> && std::is_signed_v<Type>)
|
||||
else if constexpr (is_integral_v<Type> && is_signed_v<Type>)
|
||||
writeVarInt(static_cast<Int64>(value), buf);
|
||||
else
|
||||
{
|
||||
@ -106,13 +106,13 @@ void SettingNumber<Type>::serialize(WriteBuffer & buf) const
|
||||
template <typename Type>
|
||||
void SettingNumber<Type>::deserialize(ReadBuffer & buf)
|
||||
{
|
||||
if constexpr (std::is_integral_v<Type> && std::is_unsigned_v<Type>)
|
||||
if constexpr (is_integral_v<Type> && is_unsigned_v<Type>)
|
||||
{
|
||||
UInt64 x;
|
||||
readVarUInt(x, buf);
|
||||
set(static_cast<Type>(x));
|
||||
}
|
||||
else if constexpr (std::is_integral_v<Type> && std::is_signed_v<Type>)
|
||||
else if constexpr (is_integral_v<Type> && is_signed_v<Type>)
|
||||
{
|
||||
Int64 x;
|
||||
readVarInt(x, buf);
|
||||
|
@ -311,8 +311,8 @@ private:
|
||||
using SetFieldFunction = void (*)(Derived &, const Field &);
|
||||
using SerializeFunction = void (*)(const Derived &, WriteBuffer & buf);
|
||||
using DeserializeFunction = void (*)(Derived &, ReadBuffer & buf);
|
||||
using CastValueWithoutApplyingFunction = Field (*)(const Field &);
|
||||
|
||||
using ValueToStringFunction = String (*)(const Field &);
|
||||
using ValueToCorrespondingTypeFunction = Field (*)(const Field &);
|
||||
|
||||
struct MemberInfo
|
||||
{
|
||||
@ -325,9 +325,8 @@ private:
|
||||
SetFieldFunction set_field;
|
||||
SerializeFunction serialize;
|
||||
DeserializeFunction deserialize;
|
||||
CastValueWithoutApplyingFunction cast_value_without_applying;
|
||||
|
||||
bool isChanged(const Derived & collection) const { return is_changed(collection); }
|
||||
ValueToStringFunction value_to_string;
|
||||
ValueToCorrespondingTypeFunction value_to_corresponding_type;
|
||||
};
|
||||
|
||||
class MemberInfos : private boost::noncopyable
|
||||
@ -394,7 +393,7 @@ public:
|
||||
const_reference(const const_reference & src) = default;
|
||||
const StringRef & getName() const { return member->name; }
|
||||
const StringRef & getDescription() const { return member->description; }
|
||||
bool isChanged() const { return member->isChanged(*collection); }
|
||||
bool isChanged() const { return member->is_changed(*collection); }
|
||||
Field getValue() const;
|
||||
String getValueAsString() const { return member->get_string(*collection); }
|
||||
protected:
|
||||
@ -457,16 +456,20 @@ public:
|
||||
static StringRef getDescription(const String & name) { return members().findStrict(name)->description; }
|
||||
|
||||
/// Searches a setting by its name; returns `npos` if not found.
|
||||
static size_t findIndex(const String & name) { return members().findIndex(name); }
|
||||
static size_t findIndex(const StringRef & name) { return members().findIndex(name); }
|
||||
static constexpr size_t npos = static_cast<size_t>(-1);
|
||||
|
||||
/// Searches a setting by its name; throws an exception if not found.
|
||||
static size_t findIndexStrict(const String & name) { return members().findIndexStrict(name); }
|
||||
static size_t findIndexStrict(const StringRef & name) { return members().findIndexStrict(name); }
|
||||
|
||||
/// Casts a value to a string according to a specified setting without actual changing this settings.
|
||||
static String valueToString(size_t index, const Field & value);
|
||||
static String valueToString(const StringRef & name, const Field & value);
|
||||
|
||||
/// Casts a value to a type according to a specified setting without actual changing this settings.
|
||||
/// E.g. for SettingInt64 it casts Field to Field::Types::Int64.
|
||||
static Field castValueWithoutApplying(size_t index, const Field & value);
|
||||
static Field castValueWithoutApplying(const String & name, const Field & value);
|
||||
static Field valueToCorrespondingType(size_t index, const Field & value);
|
||||
static Field valueToCorrespondingType(const StringRef & name, const Field & value);
|
||||
|
||||
iterator begin() { return iterator(castToDerived(), members().begin()); }
|
||||
const_iterator begin() const { return const_iterator(castToDerived(), members().begin()); }
|
||||
@ -475,39 +478,39 @@ public:
|
||||
|
||||
/// Returns a proxy object for accessing to a setting. Throws an exception if there is not setting with such name.
|
||||
reference operator[](size_t index) { return reference(castToDerived(), members()[index]); }
|
||||
reference operator[](const String & name) { return reference(castToDerived(), *(members().findStrict(name))); }
|
||||
reference operator[](const StringRef & name) { return reference(castToDerived(), *(members().findStrict(name))); }
|
||||
const_reference operator[](size_t index) const { return const_reference(castToDerived(), members()[index]); }
|
||||
const_reference operator[](const String & name) const { return const_reference(castToDerived(), *(members().findStrict(name))); }
|
||||
const_reference operator[](const StringRef & name) const { return const_reference(castToDerived(), *(members().findStrict(name))); }
|
||||
|
||||
/// Searches a setting by its name; returns end() if not found.
|
||||
iterator find(const String & name) { return iterator(castToDerived(), members().find(name)); }
|
||||
const_iterator find(const String & name) const { return const_iterator(castToDerived(), members().find(name)); }
|
||||
iterator find(const StringRef & name) { return iterator(castToDerived(), members().find(name)); }
|
||||
const_iterator find(const StringRef & name) const { return const_iterator(castToDerived(), members().find(name)); }
|
||||
|
||||
/// Searches a setting by its name; throws an exception if not found.
|
||||
iterator findStrict(const String & name) { return iterator(castToDerived(), members().findStrict(name)); }
|
||||
const_iterator findStrict(const String & name) const { return const_iterator(castToDerived(), members().findStrict(name)); }
|
||||
iterator findStrict(const StringRef & name) { return iterator(castToDerived(), members().findStrict(name)); }
|
||||
const_iterator findStrict(const StringRef & name) const { return const_iterator(castToDerived(), members().findStrict(name)); }
|
||||
|
||||
/// Sets setting's value.
|
||||
void set(size_t index, const Field & value);
|
||||
void set(const String & name, const Field & value);
|
||||
void set(const StringRef & name, const Field & value);
|
||||
|
||||
/// Sets setting's value. Read value in text form from string (for example, from configuration file or from URL parameter).
|
||||
void set(size_t index, const String & value) { (*this)[index].setValue(value); }
|
||||
void set(const String & name, const String & value) { (*this)[name].setValue(value); }
|
||||
void set(const StringRef & name, const String & value) { (*this)[name].setValue(value); }
|
||||
|
||||
/// Returns value of a setting.
|
||||
Field get(size_t index) const;
|
||||
Field get(const String & name) const;
|
||||
Field get(const StringRef & name) const;
|
||||
|
||||
/// Returns value of a setting converted to string.
|
||||
String getAsString(size_t index) const { return (*this)[index].getValueAsString(); }
|
||||
String getAsString(const String & name) const { return (*this)[name].getValueAsString(); }
|
||||
String getAsString(const StringRef & name) const { return (*this)[name].getValueAsString(); }
|
||||
|
||||
/// Returns value of a setting; returns false if there is no setting with the specified name.
|
||||
bool tryGet(const String & name, Field & value) const;
|
||||
bool tryGet(const StringRef & name, Field & value) const;
|
||||
|
||||
/// Returns value of a setting converted to string; returns false if there is no setting with the specified name.
|
||||
bool tryGet(const String & name, String & value) const;
|
||||
bool tryGet(const StringRef & name, String & value) const;
|
||||
|
||||
/// Compares two collections of settings.
|
||||
bool operator ==(const Derived & rhs) const;
|
||||
@ -537,7 +540,7 @@ public:
|
||||
{
|
||||
for (const auto & member : members())
|
||||
{
|
||||
if (member.isChanged(castToDerived()))
|
||||
if (member.is_changed(castToDerived()))
|
||||
{
|
||||
details::SettingsCollectionUtils::serializeName(member.name, buf);
|
||||
member.serialize(castToDerived(), buf);
|
||||
@ -600,7 +603,8 @@ public:
|
||||
static void NAME##_setField(Derived & collection, const Field & value) { collection.NAME.set(value); } \
|
||||
static void NAME##_serialize(const Derived & collection, WriteBuffer & buf) { collection.NAME.serialize(buf); } \
|
||||
static void NAME##_deserialize(Derived & collection, ReadBuffer & buf) { collection.NAME.deserialize(buf); } \
|
||||
static Field NAME##_castValueWithoutApplying(const Field & value) { TYPE temp{DEFAULT}; temp.set(value); return temp.toField(); } \
|
||||
static String NAME##_valueToString(const Field & value) { TYPE temp{DEFAULT}; temp.set(value); return temp.toString(); } \
|
||||
static Field NAME##_valueToCorrespondingType(const Field & value) { TYPE temp{DEFAULT}; temp.set(value); return temp.toField(); } \
|
||||
|
||||
|
||||
#define IMPLEMENT_SETTINGS_COLLECTION_ADD_MEMBER_INFO_HELPER_(TYPE, NAME, DEFAULT, DESCRIPTION) \
|
||||
@ -609,5 +613,5 @@ public:
|
||||
&Functions::NAME##_getString, &Functions::NAME##_getField, \
|
||||
&Functions::NAME##_setString, &Functions::NAME##_setField, \
|
||||
&Functions::NAME##_serialize, &Functions::NAME##_deserialize, \
|
||||
&Functions::NAME##_castValueWithoutApplying });
|
||||
&Functions::NAME##_valueToString, &Functions::NAME##_valueToCorrespondingType});
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <common/Types.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -18,15 +18,17 @@
|
||||
|
||||
namespace DB
|
||||
{
|
||||
std::ostream & operator<<(std::ostream & stream, const IBlockInputStream & what)
|
||||
|
||||
template <>
|
||||
std::ostream & operator<< <Field>(std::ostream & stream, const Field & what)
|
||||
{
|
||||
stream << "IBlockInputStream(name = " << what.getName() << ")";
|
||||
stream << applyVisitor(FieldVisitorDump(), what);
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & stream, const Field & what)
|
||||
std::ostream & operator<<(std::ostream & stream, const IBlockInputStream & what)
|
||||
{
|
||||
stream << applyVisitor(FieldVisitorDump(), what);
|
||||
stream << "IBlockInputStream(name = " << what.getName() << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -102,14 +104,6 @@ std::ostream & operator<<(std::ostream & stream, const Connection::Packet & what
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & stream, const IAST & what)
|
||||
{
|
||||
stream << "IAST{";
|
||||
what.dumpTree(stream);
|
||||
stream << "}";
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & stream, const ExpressionAction & what)
|
||||
{
|
||||
stream << "ExpressionAction(" << what.toString() << ")";
|
||||
|
@ -7,18 +7,15 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
// Used to disable implicit casting for certain overloaded types such as Field, which leads to
|
||||
// overload resolution ambiguity.
|
||||
template <typename T> struct Dumpable;
|
||||
template <typename T>
|
||||
std::ostream & operator<<(std::ostream & stream, const typename Dumpable<T>::Type & what);
|
||||
// Use template to disable implicit casting for certain overloaded types such as Field, which leads
|
||||
// to overload resolution ambiguity.
|
||||
class Field;
|
||||
template <typename T, typename U = std::enable_if_t<std::is_same_v<T, Field>>>
|
||||
std::ostream & operator<<(std::ostream & stream, const T & what);
|
||||
|
||||
class IBlockInputStream;
|
||||
std::ostream & operator<<(std::ostream & stream, const IBlockInputStream & what);
|
||||
|
||||
class Field;
|
||||
template <> struct Dumpable<Field> { using Type = Field; };
|
||||
|
||||
struct NameAndTypePair;
|
||||
std::ostream & operator<<(std::ostream & stream, const NameAndTypePair & what);
|
||||
|
||||
@ -43,9 +40,6 @@ std::ostream & operator<<(std::ostream & stream, const ColumnWithTypeAndName & w
|
||||
class IColumn;
|
||||
std::ostream & operator<<(std::ostream & stream, const IColumn & what);
|
||||
|
||||
class IAST;
|
||||
std::ostream & operator<<(std::ostream & stream, const IAST & what);
|
||||
|
||||
std::ostream & operator<<(std::ostream & stream, const Connection::Packet & what);
|
||||
|
||||
struct ExpressionAction;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
#include <DataTypes/DataTypeDate.h>
|
||||
#include <DataTypes/DataTypeDateTime.h>
|
||||
#include <DataTypes/DataTypeDateTime64.h>
|
||||
#include <DataTypes/DataTypeEnum.h>
|
||||
#include <DataTypes/DataTypeUUID.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
|
@ -33,6 +33,9 @@ struct BlockIO
|
||||
std::function<void(IBlockInputStream *, IBlockOutputStream *)> finish_callback;
|
||||
std::function<void()> exception_callback;
|
||||
|
||||
/// When it is true, don't bother sending any non-empty blocks to the out stream
|
||||
bool null_format = false;
|
||||
|
||||
/// Call these functions if you want to log the request.
|
||||
void onFinish()
|
||||
{
|
||||
|
91
dbms/src/DataStreams/ExecutionSpeedLimits.cpp
Normal file
91
dbms/src/DataStreams/ExecutionSpeedLimits.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include <DataStreams/ExecutionSpeedLimits.h>
|
||||
|
||||
#include <Common/ProfileEvents.h>
|
||||
#include <Common/CurrentThread.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <common/sleep.h>
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event ThrottlerSleepMicroseconds;
|
||||
}
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int TOO_SLOW;
|
||||
}
|
||||
|
||||
static void limitProgressingSpeed(size_t total_progress_size, size_t max_speed_in_seconds, UInt64 total_elapsed_microseconds)
|
||||
{
|
||||
/// How much time to wait for the average speed to become `max_speed_in_seconds`.
|
||||
UInt64 desired_microseconds = total_progress_size * 1000000 / max_speed_in_seconds;
|
||||
|
||||
if (desired_microseconds > total_elapsed_microseconds)
|
||||
{
|
||||
UInt64 sleep_microseconds = desired_microseconds - total_elapsed_microseconds;
|
||||
|
||||
/// Never sleep more than one second (it should be enough to limit speed for a reasonable amount, and otherwise it's too easy to make query hang).
|
||||
sleep_microseconds = std::min(UInt64(1000000), sleep_microseconds);
|
||||
|
||||
sleepForMicroseconds(sleep_microseconds);
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::ThrottlerSleepMicroseconds, sleep_microseconds);
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutionSpeedLimits::throttle(
|
||||
size_t read_rows, size_t read_bytes,
|
||||
size_t total_rows_to_read, UInt64 total_elapsed_microseconds)
|
||||
{
|
||||
if ((min_execution_rps != 0 || max_execution_rps != 0
|
||||
|| min_execution_bps != 0 || max_execution_bps != 0
|
||||
|| (total_rows_to_read != 0 && timeout_before_checking_execution_speed != 0)) &&
|
||||
(static_cast<Int64>(total_elapsed_microseconds) > timeout_before_checking_execution_speed.totalMicroseconds()))
|
||||
{
|
||||
/// Do not count sleeps in throttlers
|
||||
UInt64 throttler_sleep_microseconds = CurrentThread::getProfileEvents()[ProfileEvents::ThrottlerSleepMicroseconds];
|
||||
|
||||
double elapsed_seconds = 0;
|
||||
if (throttler_sleep_microseconds > total_elapsed_microseconds)
|
||||
elapsed_seconds = static_cast<double>(total_elapsed_microseconds - throttler_sleep_microseconds) / 1000000.0;
|
||||
|
||||
if (elapsed_seconds > 0)
|
||||
{
|
||||
auto rows_per_second = read_rows / elapsed_seconds;
|
||||
if (min_execution_rps && rows_per_second < min_execution_rps)
|
||||
throw Exception("Query is executing too slow: " + toString(read_rows / elapsed_seconds)
|
||||
+ " rows/sec., minimum: " + toString(min_execution_rps),
|
||||
ErrorCodes::TOO_SLOW);
|
||||
|
||||
auto bytes_per_second = read_bytes / elapsed_seconds;
|
||||
if (min_execution_bps && bytes_per_second < min_execution_bps)
|
||||
throw Exception("Query is executing too slow: " + toString(read_bytes / elapsed_seconds)
|
||||
+ " bytes/sec., minimum: " + toString(min_execution_bps),
|
||||
ErrorCodes::TOO_SLOW);
|
||||
|
||||
/// If the predicted execution time is longer than `max_execution_time`.
|
||||
if (max_execution_time != 0 && total_rows_to_read && read_rows)
|
||||
{
|
||||
double estimated_execution_time_seconds = elapsed_seconds * (static_cast<double>(total_rows_to_read) / read_rows);
|
||||
|
||||
if (estimated_execution_time_seconds > max_execution_time.totalSeconds())
|
||||
throw Exception("Estimated query execution time (" + toString(estimated_execution_time_seconds) + " seconds)"
|
||||
+ " is too long. Maximum: " + toString(max_execution_time.totalSeconds())
|
||||
+ ". Estimated rows to process: " + toString(total_rows_to_read),
|
||||
ErrorCodes::TOO_SLOW);
|
||||
}
|
||||
|
||||
if (max_execution_rps && rows_per_second >= max_execution_rps)
|
||||
limitProgressingSpeed(read_rows, max_execution_rps, total_elapsed_microseconds);
|
||||
|
||||
if (max_execution_bps && bytes_per_second >= max_execution_bps)
|
||||
limitProgressingSpeed(read_bytes, max_execution_bps, total_elapsed_microseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
dbms/src/DataStreams/ExecutionSpeedLimits.h
Normal file
29
dbms/src/DataStreams/ExecutionSpeedLimits.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <Poco/Timespan.h>
|
||||
#include <Core/Types.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/// Limits for query execution speed.
|
||||
class ExecutionSpeedLimits
|
||||
{
|
||||
public:
|
||||
/// For rows per second.
|
||||
size_t min_execution_rps = 0;
|
||||
size_t max_execution_rps = 0;
|
||||
/// For bytes per second.
|
||||
size_t min_execution_bps = 0;
|
||||
size_t max_execution_bps = 0;
|
||||
|
||||
Poco::Timespan max_execution_time = 0;
|
||||
/// Verify that the speed is not too low after the specified time has elapsed.
|
||||
Poco::Timespan timeout_before_checking_execution_speed = 0;
|
||||
|
||||
/// Pause execution in case if speed limits were exceeded.
|
||||
void throttle(size_t read_rows, size_t read_bytes, size_t total_rows_to_read, UInt64 total_elapsed_microseconds);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ Graphite::RollupRule GraphiteRollupSortedBlockInputStream::selectPatternForPath(
|
||||
|
||||
UInt32 GraphiteRollupSortedBlockInputStream::selectPrecision(const Graphite::Retentions & retentions, time_t time) const
|
||||
{
|
||||
static_assert(std::is_signed_v<time_t>, "time_t must be signed type");
|
||||
static_assert(is_signed_v<time_t>, "time_t must be signed type");
|
||||
|
||||
for (const auto & retention : retentions)
|
||||
{
|
||||
|
@ -219,11 +219,11 @@ static bool handleOverflowMode(OverflowMode mode, const String & message, int co
|
||||
|
||||
bool IBlockInputStream::checkTimeLimit()
|
||||
{
|
||||
if (limits.max_execution_time != 0
|
||||
&& info.total_stopwatch.elapsed() > static_cast<UInt64>(limits.max_execution_time.totalMicroseconds()) * 1000)
|
||||
if (limits.speed_limits.max_execution_time != 0
|
||||
&& info.total_stopwatch.elapsed() > static_cast<UInt64>(limits.speed_limits.max_execution_time.totalMicroseconds()) * 1000)
|
||||
return handleOverflowMode(limits.timeout_overflow_mode,
|
||||
"Timeout exceeded: elapsed " + toString(info.total_stopwatch.elapsedSeconds())
|
||||
+ " seconds, maximum: " + toString(limits.max_execution_time.totalMicroseconds() / 1000000.0),
|
||||
+ " seconds, maximum: " + toString(limits.speed_limits.max_execution_time.totalMicroseconds() / 1000000.0),
|
||||
ErrorCodes::TIMEOUT_EXCEEDED);
|
||||
|
||||
return true;
|
||||
@ -252,24 +252,6 @@ void IBlockInputStream::checkQuota(Block & block)
|
||||
}
|
||||
}
|
||||
|
||||
static void limitProgressingSpeed(size_t total_progress_size, size_t max_speed_in_seconds, UInt64 total_elapsed_microseconds)
|
||||
{
|
||||
/// How much time to wait for the average speed to become `max_speed_in_seconds`.
|
||||
UInt64 desired_microseconds = total_progress_size * 1000000 / max_speed_in_seconds;
|
||||
|
||||
if (desired_microseconds > total_elapsed_microseconds)
|
||||
{
|
||||
UInt64 sleep_microseconds = desired_microseconds - total_elapsed_microseconds;
|
||||
|
||||
/// Never sleep more than one second (it should be enough to limit speed for a reasonable amount, and otherwise it's too easy to make query hang).
|
||||
sleep_microseconds = std::min(UInt64(1000000), sleep_microseconds);
|
||||
|
||||
sleepForMicroseconds(sleep_microseconds);
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::ThrottlerSleepMicroseconds, sleep_microseconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IBlockInputStream::progressImpl(const Progress & value)
|
||||
{
|
||||
@ -289,40 +271,11 @@ void IBlockInputStream::progressImpl(const Progress & value)
|
||||
/** Check the restrictions on the amount of data to read, the speed of the query, the quota on the amount of data to read.
|
||||
* NOTE: Maybe it makes sense to have them checked directly in ProcessList?
|
||||
*/
|
||||
|
||||
if (limits.mode == LIMITS_TOTAL
|
||||
&& ((limits.size_limits.max_rows && total_rows_estimate > limits.size_limits.max_rows)
|
||||
|| (limits.size_limits.max_bytes && progress.read_bytes > limits.size_limits.max_bytes)))
|
||||
if (limits.mode == LIMITS_TOTAL)
|
||||
{
|
||||
switch (limits.size_limits.overflow_mode)
|
||||
{
|
||||
case OverflowMode::THROW:
|
||||
{
|
||||
if (limits.size_limits.max_rows && total_rows_estimate > limits.size_limits.max_rows)
|
||||
throw Exception("Limit for rows to read exceeded: " + toString(total_rows_estimate)
|
||||
+ " rows read (or to read), maximum: " + toString(limits.size_limits.max_rows),
|
||||
ErrorCodes::TOO_MANY_ROWS);
|
||||
else
|
||||
throw Exception("Limit for (uncompressed) bytes to read exceeded: " + toString(progress.read_bytes)
|
||||
+ " bytes read, maximum: " + toString(limits.size_limits.max_bytes),
|
||||
ErrorCodes::TOO_MANY_BYTES);
|
||||
}
|
||||
|
||||
case OverflowMode::BREAK:
|
||||
{
|
||||
/// For `break`, we will stop only if so many rows were actually read, and not just supposed to be read.
|
||||
if ((limits.size_limits.max_rows && progress.read_rows > limits.size_limits.max_rows)
|
||||
|| (limits.size_limits.max_bytes && progress.read_bytes > limits.size_limits.max_bytes))
|
||||
{
|
||||
cancel(false);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw Exception("Logical error: unknown overflow mode", ErrorCodes::LOGICAL_ERROR);
|
||||
}
|
||||
if (!limits.size_limits.check(total_rows_estimate, progress.read_bytes, "rows to read",
|
||||
ErrorCodes::TOO_MANY_ROWS, ErrorCodes::TOO_MANY_BYTES))
|
||||
cancel(false);
|
||||
}
|
||||
|
||||
size_t total_rows = progress.total_rows_to_read;
|
||||
@ -336,46 +289,7 @@ void IBlockInputStream::progressImpl(const Progress & value)
|
||||
last_profile_events_update_time = total_elapsed_microseconds;
|
||||
}
|
||||
|
||||
if ((limits.min_execution_speed || limits.max_execution_speed || limits.min_execution_speed_bytes ||
|
||||
limits.max_execution_speed_bytes || (total_rows && limits.timeout_before_checking_execution_speed != 0)) &&
|
||||
(static_cast<Int64>(total_elapsed_microseconds) > limits.timeout_before_checking_execution_speed.totalMicroseconds()))
|
||||
{
|
||||
/// Do not count sleeps in throttlers
|
||||
UInt64 throttler_sleep_microseconds = CurrentThread::getProfileEvents()[ProfileEvents::ThrottlerSleepMicroseconds];
|
||||
double elapsed_seconds = (throttler_sleep_microseconds > total_elapsed_microseconds)
|
||||
? 0.0 : (total_elapsed_microseconds - throttler_sleep_microseconds) / 1000000.0;
|
||||
|
||||
if (elapsed_seconds > 0)
|
||||
{
|
||||
if (limits.min_execution_speed && progress.read_rows / elapsed_seconds < limits.min_execution_speed)
|
||||
throw Exception("Query is executing too slow: " + toString(progress.read_rows / elapsed_seconds)
|
||||
+ " rows/sec., minimum: " + toString(limits.min_execution_speed),
|
||||
ErrorCodes::TOO_SLOW);
|
||||
|
||||
if (limits.min_execution_speed_bytes && progress.read_bytes / elapsed_seconds < limits.min_execution_speed_bytes)
|
||||
throw Exception("Query is executing too slow: " + toString(progress.read_bytes / elapsed_seconds)
|
||||
+ " bytes/sec., minimum: " + toString(limits.min_execution_speed_bytes),
|
||||
ErrorCodes::TOO_SLOW);
|
||||
|
||||
/// If the predicted execution time is longer than `max_execution_time`.
|
||||
if (limits.max_execution_time != 0 && total_rows && progress.read_rows)
|
||||
{
|
||||
double estimated_execution_time_seconds = elapsed_seconds * (static_cast<double>(total_rows) / progress.read_rows);
|
||||
|
||||
if (estimated_execution_time_seconds > limits.max_execution_time.totalSeconds())
|
||||
throw Exception("Estimated query execution time (" + toString(estimated_execution_time_seconds) + " seconds)"
|
||||
+ " is too long. Maximum: " + toString(limits.max_execution_time.totalSeconds())
|
||||
+ ". Estimated rows to process: " + toString(total_rows),
|
||||
ErrorCodes::TOO_SLOW);
|
||||
}
|
||||
|
||||
if (limits.max_execution_speed && progress.read_rows / elapsed_seconds >= limits.max_execution_speed)
|
||||
limitProgressingSpeed(progress.read_rows, limits.max_execution_speed, total_elapsed_microseconds);
|
||||
|
||||
if (limits.max_execution_speed_bytes && progress.read_bytes / elapsed_seconds >= limits.max_execution_speed_bytes)
|
||||
limitProgressingSpeed(progress.read_bytes, limits.max_execution_speed_bytes, total_elapsed_microseconds);
|
||||
}
|
||||
}
|
||||
limits.speed_limits.throttle(progress.read_rows, progress.read_bytes, total_rows, total_elapsed_microseconds);
|
||||
|
||||
if (quota != nullptr && limits.mode == LIMITS_TOTAL)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <DataStreams/BlockStreamProfileInfo.h>
|
||||
#include <DataStreams/IBlockStream_fwd.h>
|
||||
#include <DataStreams/SizeLimits.h>
|
||||
#include <DataStreams/ExecutionSpeedLimits.h>
|
||||
#include <IO/Progress.h>
|
||||
#include <Storages/TableStructureLockHolder.h>
|
||||
#include <Common/TypePromotion.h>
|
||||
@ -137,7 +138,7 @@ public:
|
||||
* The function takes the number of rows in the last block, the number of bytes in the last block.
|
||||
* Note that the callback can be called from different threads.
|
||||
*/
|
||||
void setProgressCallback(const ProgressCallback & callback);
|
||||
virtual void setProgressCallback(const ProgressCallback & callback);
|
||||
|
||||
|
||||
/** In this method:
|
||||
@ -162,11 +163,11 @@ public:
|
||||
* Based on this information, the quota and some restrictions will be checked.
|
||||
* This information will also be available in the SHOW PROCESSLIST request.
|
||||
*/
|
||||
void setProcessListElement(QueryStatus * elem);
|
||||
virtual void setProcessListElement(QueryStatus * elem);
|
||||
|
||||
/** Set the approximate total number of rows to read.
|
||||
*/
|
||||
void addTotalRowsApprox(size_t value) { total_rows_approx += value; }
|
||||
virtual void addTotalRowsApprox(size_t value) { total_rows_approx += value; }
|
||||
|
||||
|
||||
/** Ask to abort the receipt of data as soon as possible.
|
||||
@ -201,20 +202,13 @@ public:
|
||||
|
||||
SizeLimits size_limits;
|
||||
|
||||
Poco::Timespan max_execution_time = 0;
|
||||
OverflowMode timeout_overflow_mode = OverflowMode::THROW;
|
||||
ExecutionSpeedLimits speed_limits;
|
||||
|
||||
/// in rows per second
|
||||
size_t min_execution_speed = 0;
|
||||
size_t max_execution_speed = 0;
|
||||
size_t min_execution_speed_bytes = 0;
|
||||
size_t max_execution_speed_bytes = 0;
|
||||
/// Verify that the speed is not too low after the specified time has elapsed.
|
||||
Poco::Timespan timeout_before_checking_execution_speed = 0;
|
||||
OverflowMode timeout_overflow_mode = OverflowMode::THROW;
|
||||
};
|
||||
|
||||
/** Set limitations that checked on each block. */
|
||||
void setLimits(const LocalLimits & limits_)
|
||||
virtual void setLimits(const LocalLimits & limits_)
|
||||
{
|
||||
limits = limits_;
|
||||
}
|
||||
@ -227,7 +221,7 @@ public:
|
||||
/** Set the quota. If you set a quota on the amount of raw data,
|
||||
* then you should also set mode = LIMITS_TOTAL to LocalLimits with setLimits.
|
||||
*/
|
||||
void setQuota(QuotaForIntervals & quota_)
|
||||
virtual void setQuota(QuotaForIntervals & quota_)
|
||||
{
|
||||
quota = "a_;
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ namespace ErrorCodes
|
||||
RemoteBlockInputStream::RemoteBlockInputStream(
|
||||
Connection & connection,
|
||||
const String & query_, const Block & header_, const Context & context_, const Settings * settings,
|
||||
const ThrottlerPtr & throttler, const Tables & external_tables_, QueryProcessingStage::Enum stage_)
|
||||
: header(header_), query(query_), context(context_), external_tables(external_tables_), stage(stage_)
|
||||
const ThrottlerPtr & throttler, const Scalars & scalars_, const Tables & external_tables_, QueryProcessingStage::Enum stage_)
|
||||
: header(header_), query(query_), context(context_), scalars(scalars_), external_tables(external_tables_), stage(stage_)
|
||||
{
|
||||
if (settings)
|
||||
context.setSettings(*settings);
|
||||
@ -38,8 +38,8 @@ RemoteBlockInputStream::RemoteBlockInputStream(
|
||||
RemoteBlockInputStream::RemoteBlockInputStream(
|
||||
std::vector<IConnectionPool::Entry> && connections,
|
||||
const String & query_, const Block & header_, const Context & context_, const Settings * settings,
|
||||
const ThrottlerPtr & throttler, const Tables & external_tables_, QueryProcessingStage::Enum stage_)
|
||||
: header(header_), query(query_), context(context_), external_tables(external_tables_), stage(stage_)
|
||||
const ThrottlerPtr & throttler, const Scalars & scalars_, const Tables & external_tables_, QueryProcessingStage::Enum stage_)
|
||||
: header(header_), query(query_), context(context_), scalars(scalars_), external_tables(external_tables_), stage(stage_)
|
||||
{
|
||||
if (settings)
|
||||
context.setSettings(*settings);
|
||||
@ -54,8 +54,8 @@ RemoteBlockInputStream::RemoteBlockInputStream(
|
||||
RemoteBlockInputStream::RemoteBlockInputStream(
|
||||
const ConnectionPoolWithFailoverPtr & pool,
|
||||
const String & query_, const Block & header_, const Context & context_, const Settings * settings,
|
||||
const ThrottlerPtr & throttler, const Tables & external_tables_, QueryProcessingStage::Enum stage_)
|
||||
: header(header_), query(query_), context(context_), external_tables(external_tables_), stage(stage_)
|
||||
const ThrottlerPtr & throttler, const Scalars & scalars_, const Tables & external_tables_, QueryProcessingStage::Enum stage_)
|
||||
: header(header_), query(query_), context(context_), scalars(scalars_), external_tables(external_tables_), stage(stage_)
|
||||
{
|
||||
if (settings)
|
||||
context.setSettings(*settings);
|
||||
@ -120,6 +120,11 @@ void RemoteBlockInputStream::cancel(bool kill)
|
||||
tryCancel("Cancelling query");
|
||||
}
|
||||
|
||||
void RemoteBlockInputStream::sendScalars()
|
||||
{
|
||||
multiplexed_connections->sendScalarsData(scalars);
|
||||
}
|
||||
|
||||
void RemoteBlockInputStream::sendExternalTables()
|
||||
{
|
||||
size_t count = multiplexed_connections->size();
|
||||
@ -308,6 +313,8 @@ void RemoteBlockInputStream::sendQuery()
|
||||
established = false;
|
||||
sent_query = true;
|
||||
|
||||
if (settings.enable_scalar_subquery_optimization)
|
||||
sendScalars();
|
||||
sendExternalTables();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
RemoteBlockInputStream(
|
||||
Connection & connection,
|
||||
const String & query_, const Block & header_, const Context & context_, const Settings * settings = nullptr,
|
||||
const ThrottlerPtr & throttler = nullptr, const Tables & external_tables_ = Tables(),
|
||||
const ThrottlerPtr & throttler = nullptr, const Scalars & scalars_ = Scalars(), const Tables & external_tables_ = Tables(),
|
||||
QueryProcessingStage::Enum stage_ = QueryProcessingStage::Complete);
|
||||
|
||||
/// Accepts several connections already taken from pool.
|
||||
@ -33,7 +33,7 @@ public:
|
||||
RemoteBlockInputStream(
|
||||
std::vector<IConnectionPool::Entry> && connections,
|
||||
const String & query_, const Block & header_, const Context & context_, const Settings * settings = nullptr,
|
||||
const ThrottlerPtr & throttler = nullptr, const Tables & external_tables_ = Tables(),
|
||||
const ThrottlerPtr & throttler = nullptr, const Scalars & scalars_ = Scalars(), const Tables & external_tables_ = Tables(),
|
||||
QueryProcessingStage::Enum stage_ = QueryProcessingStage::Complete);
|
||||
|
||||
/// Takes a pool and gets one or several connections from it.
|
||||
@ -41,7 +41,7 @@ public:
|
||||
RemoteBlockInputStream(
|
||||
const ConnectionPoolWithFailoverPtr & pool,
|
||||
const String & query_, const Block & header_, const Context & context_, const Settings * settings = nullptr,
|
||||
const ThrottlerPtr & throttler = nullptr, const Tables & external_tables_ = Tables(),
|
||||
const ThrottlerPtr & throttler = nullptr, const Scalars & scalars_ = Scalars(), const Tables & external_tables_ = Tables(),
|
||||
QueryProcessingStage::Enum stage_ = QueryProcessingStage::Complete);
|
||||
|
||||
~RemoteBlockInputStream() override;
|
||||
@ -71,6 +71,9 @@ public:
|
||||
Block getHeader() const override { return header; }
|
||||
|
||||
protected:
|
||||
/// Send all scalars to remote servers
|
||||
void sendScalars();
|
||||
|
||||
/// Send all temporary tables to remote servers
|
||||
void sendExternalTables();
|
||||
|
||||
@ -103,6 +106,8 @@ private:
|
||||
String query_id = "";
|
||||
Context context;
|
||||
|
||||
/// Scalars needed to be sent to remote servers
|
||||
Scalars scalars;
|
||||
/// Temporary tables needed to be sent to remote servers
|
||||
Tables external_tables;
|
||||
QueryProcessingStage::Enum stage;
|
||||
|
@ -7,17 +7,17 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
bool SizeLimits::check(UInt64 rows, UInt64 bytes, const char * what, int exception_code) const
|
||||
bool SizeLimits::check(UInt64 rows, UInt64 bytes, const char * what, int too_many_rows_exception_code, int too_many_bytes_exception_code) const
|
||||
{
|
||||
if (overflow_mode == OverflowMode::THROW)
|
||||
{
|
||||
if (max_rows && rows > max_rows)
|
||||
throw Exception("Limit for " + std::string(what) + " exceeded, max rows: " + formatReadableQuantity(max_rows)
|
||||
+ ", current rows: " + formatReadableQuantity(rows), exception_code);
|
||||
+ ", current rows: " + formatReadableQuantity(rows), too_many_rows_exception_code);
|
||||
|
||||
if (max_bytes && bytes > max_bytes)
|
||||
throw Exception("Limit for " + std::string(what) + " exceeded, max bytes: " + formatReadableSizeWithBinarySuffix(max_bytes)
|
||||
+ ", current bytes: " + formatReadableSizeWithBinarySuffix(bytes), exception_code);
|
||||
+ ", current bytes: " + formatReadableSizeWithBinarySuffix(bytes), too_many_bytes_exception_code);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -34,4 +34,9 @@ bool SizeLimits::softCheck(UInt64 rows, UInt64 bytes) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SizeLimits::check(UInt64 rows, UInt64 bytes, const char * what, int exception_code) const
|
||||
{
|
||||
return check(rows, bytes, what, exception_code, exception_code);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ struct SizeLimits
|
||||
: max_rows(max_rows_), max_bytes(max_bytes_), overflow_mode(overflow_mode_) {}
|
||||
|
||||
/// Check limits. If exceeded, return false or throw an exception, depending on overflow_mode.
|
||||
bool check(UInt64 rows, UInt64 bytes, const char * what, int too_many_rows_exception_code, int too_many_bytes_exception_code) const;
|
||||
bool check(UInt64 rows, UInt64 bytes, const char * what, int exception_code) const;
|
||||
|
||||
/// Check limits. No exceptions.
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <common/arithmeticOverflow.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Columns/ColumnDecimal.h>
|
||||
#include <Core/DecimalFunctions.h>
|
||||
#include <DataTypes/IDataType.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <DataTypes/DataTypeWithSimpleSerialization.h>
|
||||
@ -25,13 +26,6 @@ class Context;
|
||||
bool decimalCheckComparisonOverflow(const Context & context);
|
||||
bool decimalCheckArithmeticOverflow(const Context & context);
|
||||
|
||||
|
||||
static constexpr size_t minDecimalPrecision() { return 1; }
|
||||
template <typename T> static constexpr size_t maxDecimalPrecision() { return 0; }
|
||||
template <> constexpr size_t maxDecimalPrecision<Decimal32>() { return 9; }
|
||||
template <> constexpr size_t maxDecimalPrecision<Decimal64>() { return 18; }
|
||||
template <> constexpr size_t maxDecimalPrecision<Decimal128>() { return 38; }
|
||||
|
||||
inline UInt32 leastDecimalPrecisionFor(TypeIndex int_type)
|
||||
{
|
||||
switch (int_type)
|
||||
|
@ -26,7 +26,7 @@ void DataTypeNumberBase<T>::deserializeText(IColumn & column, ReadBuffer & istr,
|
||||
{
|
||||
T x;
|
||||
|
||||
if constexpr (std::is_integral_v<T> && std::is_arithmetic_v<T>)
|
||||
if constexpr (is_integral_v<T> && is_arithmetic_v<T>)
|
||||
readIntTextUnsafe(x, istr);
|
||||
else
|
||||
readText(x, istr);
|
||||
@ -68,7 +68,7 @@ void DataTypeNumberBase<T>::serializeTextJSON(const IColumn & column, size_t row
|
||||
auto x = assert_cast<const ColumnVector<T> &>(column).getData()[row_num];
|
||||
bool is_finite = isFinite(x);
|
||||
|
||||
const bool need_quote = (std::is_integral_v<T> && (sizeof(T) == 8) && settings.json.quote_64bit_integers)
|
||||
const bool need_quote = (is_integral_v<T> && (sizeof(T) == 8) && settings.json.quote_64bit_integers)
|
||||
|| (settings.json.quote_denormals && !is_finite);
|
||||
|
||||
if (need_quote)
|
||||
@ -242,13 +242,13 @@ MutableColumnPtr DataTypeNumberBase<T>::createColumn() const
|
||||
template <typename T>
|
||||
bool DataTypeNumberBase<T>::isValueRepresentedByInteger() const
|
||||
{
|
||||
return std::is_integral_v<T>;
|
||||
return is_integral_v<T>;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DataTypeNumberBase<T>::isValueRepresentedByUnsignedInteger() const
|
||||
{
|
||||
return std::is_integral_v<T> && std::is_unsigned_v<T>;
|
||||
return is_integral_v<T> && is_unsigned_v<T>;
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,9 @@ public:
|
||||
TypeIndex getTypeId() const override { return TypeIndex::Set; }
|
||||
bool equals(const IDataType & rhs) const override { return typeid(rhs) == typeid(*this); }
|
||||
bool isParametric() const override { return true; }
|
||||
|
||||
// Used only for debugging, making it DUMPABLE
|
||||
Field getDefault() const override { return Tuple(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -188,6 +188,13 @@ void DataTypeTuple::deserializeText(IColumn & column, ReadBuffer & istr, const F
|
||||
}
|
||||
});
|
||||
|
||||
// Special format for one element tuple (1,)
|
||||
if (1 == elems.size())
|
||||
{
|
||||
skipWhitespaceIfAny(istr);
|
||||
// Allow both (1) and (1,)
|
||||
checkChar(',', istr);
|
||||
}
|
||||
skipWhitespaceIfAny(istr);
|
||||
assertChar(')', istr);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ template <> struct Construct<true, true, 8> { using Type = Float64; };
|
||||
template <typename A, typename B> struct ResultOfAdditionMultiplication
|
||||
{
|
||||
using Type = typename Construct<
|
||||
std::is_signed_v<A> || std::is_signed_v<B>,
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
std::is_floating_point_v<A> || std::is_floating_point_v<B>,
|
||||
nextSize(max(sizeof(A), sizeof(B)))>::Type;
|
||||
};
|
||||
@ -91,7 +91,7 @@ template <typename A, typename B> struct ResultOfFloatingPointDivision
|
||||
template <typename A, typename B> struct ResultOfIntegerDivision
|
||||
{
|
||||
using Type = typename Construct<
|
||||
std::is_signed_v<A> || std::is_signed_v<B>,
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
false,
|
||||
sizeof(A)>::Type;
|
||||
};
|
||||
@ -101,7 +101,7 @@ template <typename A, typename B> struct ResultOfIntegerDivision
|
||||
template <typename A, typename B> struct ResultOfModulo
|
||||
{
|
||||
using Type = typename Construct<
|
||||
std::is_signed_v<A> || std::is_signed_v<B>,
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
false,
|
||||
sizeof(B)>::Type;
|
||||
};
|
||||
@ -111,7 +111,7 @@ template <typename A> struct ResultOfNegate
|
||||
using Type = typename Construct<
|
||||
true,
|
||||
std::is_floating_point_v<A>,
|
||||
std::is_signed_v<A> ? sizeof(A) : nextSize(sizeof(A))>::Type;
|
||||
is_signed_v<A> ? sizeof(A) : nextSize(sizeof(A))>::Type;
|
||||
};
|
||||
|
||||
template <typename A> struct ResultOfAbs
|
||||
@ -127,7 +127,7 @@ template <typename A> struct ResultOfAbs
|
||||
template <typename A, typename B> struct ResultOfBit
|
||||
{
|
||||
using Type = typename Construct<
|
||||
std::is_signed_v<A> || std::is_signed_v<B>,
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
false,
|
||||
std::is_floating_point_v<A> || std::is_floating_point_v<B> ? 8 : max(sizeof(A), sizeof(B))>::Type;
|
||||
};
|
||||
@ -135,7 +135,7 @@ template <typename A, typename B> struct ResultOfBit
|
||||
template <typename A> struct ResultOfBitNot
|
||||
{
|
||||
using Type = typename Construct<
|
||||
std::is_signed_v<A>,
|
||||
is_signed_v<A>,
|
||||
false,
|
||||
sizeof(A)>::Type;
|
||||
};
|
||||
@ -156,13 +156,13 @@ template <typename A, typename B>
|
||||
struct ResultOfIf
|
||||
{
|
||||
static constexpr bool has_float = std::is_floating_point_v<A> || std::is_floating_point_v<B>;
|
||||
static constexpr bool has_integer = std::is_integral_v<A> || std::is_integral_v<B>;
|
||||
static constexpr bool has_signed = std::is_signed_v<A> || std::is_signed_v<B>;
|
||||
static constexpr bool has_unsigned = !std::is_signed_v<A> || !std::is_signed_v<B>;
|
||||
static constexpr bool has_integer = is_integral_v<A> || is_integral_v<B>;
|
||||
static constexpr bool has_signed = is_signed_v<A> || is_signed_v<B>;
|
||||
static constexpr bool has_unsigned = !is_signed_v<A> || !is_signed_v<B>;
|
||||
|
||||
static constexpr size_t max_size_of_unsigned_integer = max(std::is_signed_v<A> ? 0 : sizeof(A), std::is_signed_v<B> ? 0 : sizeof(B));
|
||||
static constexpr size_t max_size_of_signed_integer = max(std::is_signed_v<A> ? sizeof(A) : 0, std::is_signed_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_integer = max(std::is_integral_v<A> ? sizeof(A) : 0, std::is_integral_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_unsigned_integer = max(is_signed_v<A> ? 0 : sizeof(A), is_signed_v<B> ? 0 : sizeof(B));
|
||||
static constexpr size_t max_size_of_signed_integer = max(is_signed_v<A> ? sizeof(A) : 0, is_signed_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_integer = max(is_integral_v<A> ? sizeof(A) : 0, is_integral_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_float = max(std::is_floating_point_v<A> ? sizeof(A) : 0, std::is_floating_point_v<B> ? sizeof(B) : 0);
|
||||
|
||||
using ConstructedType = typename Construct<has_signed, has_float,
|
||||
@ -181,7 +181,7 @@ struct ResultOfIf
|
||||
template <typename A> struct ToInteger
|
||||
{
|
||||
using Type = typename Construct<
|
||||
std::is_signed_v<A>,
|
||||
is_signed_v<A>,
|
||||
false,
|
||||
std::is_floating_point_v<A> ? 8 : sizeof(A)>::Type;
|
||||
};
|
||||
@ -191,9 +191,9 @@ template <typename A> struct ToInteger
|
||||
// NOTE: This case is applied for 64-bit integers only (for backward compatibility), but could be used for any-bit integers
|
||||
template <typename A, typename B>
|
||||
constexpr bool LeastGreatestSpecialCase =
|
||||
std::is_integral_v<A> && std::is_integral_v<B>
|
||||
is_integral_v<A> && is_integral_v<B>
|
||||
&& (8 == sizeof(A) && sizeof(A) == sizeof(B))
|
||||
&& (std::is_signed_v<A> ^ std::is_signed_v<B>);
|
||||
&& (is_signed_v<A> ^ is_signed_v<B>);
|
||||
|
||||
template <typename A, typename B>
|
||||
using ResultOfLeast = std::conditional_t<LeastGreatestSpecialCase<A, B>,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <DataTypes/DataTypeNothing.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
#include <DataTypes/DataTypeDateTime.h>
|
||||
#include <DataTypes/DataTypeDateTime64.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
|
||||
|
@ -19,6 +19,7 @@ namespace ErrorCodes
|
||||
extern const int LOGICAL_ERROR;
|
||||
extern const int CANNOT_GET_CREATE_TABLE_QUERY;
|
||||
extern const int SYNTAX_ERROR;
|
||||
extern const int UNSUPPORTED_METHOD;
|
||||
}
|
||||
|
||||
DatabaseDictionary::DatabaseDictionary(const String & name_)
|
||||
@ -27,32 +28,36 @@ DatabaseDictionary::DatabaseDictionary(const String & name_)
|
||||
{
|
||||
}
|
||||
|
||||
void DatabaseDictionary::loadTables(Context &, bool)
|
||||
void DatabaseDictionary::loadStoredObjects(Context &, bool)
|
||||
{
|
||||
}
|
||||
|
||||
Tables DatabaseDictionary::listTables(const Context & context, const FilterByNameFunction & filter_by_name)
|
||||
{
|
||||
Tables tables;
|
||||
ExternalLoader::Loadables loadables;
|
||||
ExternalLoader::LoadResults load_results;
|
||||
if (filter_by_name)
|
||||
{
|
||||
/// If `filter_by_name` is set, we iterate through all dictionaries with such names. That's why we need to load all of them.
|
||||
loadables = context.getExternalDictionariesLoader().loadAndGet(filter_by_name);
|
||||
context.getExternalDictionariesLoader().load(filter_by_name, load_results);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// If `filter_by_name` isn't set, we iterate through only already loaded dictionaries. We don't try to load all dictionaries in this case.
|
||||
loadables = context.getExternalDictionariesLoader().getCurrentlyLoadedObjects();
|
||||
load_results = context.getExternalDictionariesLoader().getCurrentLoadResults();
|
||||
}
|
||||
|
||||
for (const auto & loadable : loadables)
|
||||
for (const auto & [object_name, info]: load_results)
|
||||
{
|
||||
auto dict_ptr = std::static_pointer_cast<const IDictionaryBase>(loadable);
|
||||
auto dict_name = dict_ptr->getName();
|
||||
const DictionaryStructure & dictionary_structure = dict_ptr->getStructure();
|
||||
auto columns = StorageDictionary::getNamesAndTypes(dictionary_structure);
|
||||
tables[dict_name] = StorageDictionary::create(getDatabaseName(), dict_name, ColumnsDescription{columns}, context, true, dict_name);
|
||||
/// Load tables only from XML dictionaries, don't touch other
|
||||
if (info.object != nullptr && info.repository_name.empty())
|
||||
{
|
||||
auto dict_ptr = std::static_pointer_cast<const IDictionaryBase>(info.object);
|
||||
auto dict_name = dict_ptr->getName();
|
||||
const DictionaryStructure & dictionary_structure = dict_ptr->getStructure();
|
||||
auto columns = StorageDictionary::getNamesAndTypes(dictionary_structure);
|
||||
tables[dict_name] = StorageDictionary::create(getDatabaseName(), dict_name, ColumnsDescription{columns}, context, true, dict_name);
|
||||
}
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
@ -64,6 +69,66 @@ bool DatabaseDictionary::isTableExist(
|
||||
return context.getExternalDictionariesLoader().getCurrentStatus(table_name) != ExternalLoader::Status::NOT_EXIST;
|
||||
}
|
||||
|
||||
|
||||
bool DatabaseDictionary::isDictionaryExist(
|
||||
const Context & /*context*/,
|
||||
const String & /*table_name*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DatabaseDictionariesIteratorPtr DatabaseDictionary::getDictionariesIterator(
|
||||
const Context & /*context*/,
|
||||
const FilterByNameFunction & /*filter_by_dictionary_name*/)
|
||||
{
|
||||
return std::make_unique<DatabaseDictionariesSnapshotIterator>();
|
||||
}
|
||||
|
||||
|
||||
void DatabaseDictionary::createDictionary(
|
||||
const Context & /*context*/,
|
||||
const String & /*dictionary_name*/,
|
||||
const ASTPtr & /*query*/)
|
||||
{
|
||||
throw Exception("Dictionary engine doesn't support dictionaries.", ErrorCodes::UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
void DatabaseDictionary::removeDictionary(
|
||||
const Context & /*context*/,
|
||||
const String & /*table_name*/)
|
||||
{
|
||||
throw Exception("Dictionary engine doesn't support dictionaries.", ErrorCodes::UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
void DatabaseDictionary::attachDictionary(
|
||||
const String & /*dictionary_name*/, const Context & /*context*/, bool /*reload*/)
|
||||
{
|
||||
throw Exception("Dictionary engine doesn't support dictionaries.", ErrorCodes::UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
void DatabaseDictionary::detachDictionary(
|
||||
const String & /*dictionary_name*/, const Context & /*context*/, bool /*reload*/)
|
||||
{
|
||||
throw Exception("Dictionary engine doesn't support dictionaries.", ErrorCodes::UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
|
||||
ASTPtr DatabaseDictionary::tryGetCreateDictionaryQuery(
|
||||
const Context & /*context*/,
|
||||
const String & /*table_name*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
ASTPtr DatabaseDictionary::getCreateDictionaryQuery(
|
||||
const Context & /*context*/,
|
||||
const String & /*table_name*/) const
|
||||
{
|
||||
throw Exception("Dictionary engine doesn't support dictionaries.", ErrorCodes::UNSUPPORTED_METHOD);
|
||||
}
|
||||
|
||||
StoragePtr DatabaseDictionary::tryGetTable(
|
||||
const Context & context,
|
||||
const String & table_name) const
|
||||
@ -79,9 +144,9 @@ StoragePtr DatabaseDictionary::tryGetTable(
|
||||
return {};
|
||||
}
|
||||
|
||||
DatabaseIteratorPtr DatabaseDictionary::getIterator(const Context & context, const FilterByNameFunction & filter_by_name)
|
||||
DatabaseTablesIteratorPtr DatabaseDictionary::getTablesIterator(const Context & context, const FilterByNameFunction & filter_by_name)
|
||||
{
|
||||
return std::make_unique<DatabaseSnapshotIterator>(listTables(context, filter_by_name));
|
||||
return std::make_unique<DatabaseTablesSnapshotIterator>(listTables(context, filter_by_name));
|
||||
}
|
||||
|
||||
bool DatabaseDictionary::empty(const Context & context) const
|
||||
@ -115,7 +180,7 @@ void DatabaseDictionary::removeTable(
|
||||
throw Exception("DatabaseDictionary: removeTable() is not supported", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
time_t DatabaseDictionary::getTableMetadataModificationTime(
|
||||
time_t DatabaseDictionary::getObjectMetadataModificationTime(
|
||||
const Context &,
|
||||
const String &)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user