mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-03 13:02:00 +00:00
Merge branch 'master' into fix_01236
This commit is contained in:
commit
af845690dd
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve ClickHouse
|
||||
about: Wrong behaviour (visible to users) in official ClickHouse release.
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
111
CHANGELOG.md
111
CHANGELOG.md
@ -1,3 +1,114 @@
|
||||
### ClickHouse release v21.8, 2021-08-12
|
||||
|
||||
#### New Features
|
||||
|
||||
* Collect common system metrics (in `system.asynchronous_metrics` and `system.asynchronous_metric_log`) on CPU usage, disk usage, memory usage, IO, network, files, load average, CPU frequencies, thermal sensors, EDAC counters, system uptime; also added metrics about the scheduling jitter and the time spent collecting the metrics. It works similar to `atop` in ClickHouse and allows access to monitoring data even if you have no additional tools installed. Close [#9430](https://github.com/ClickHouse/ClickHouse/issues/9430). [#24416](https://github.com/ClickHouse/ClickHouse/pull/24416) ([Yegor Levankov](https://github.com/elevankoff)).
|
||||
* Add new functions `leftPad()`, `rightPad()`, `leftPadUTF8()`, `rightPadUTF8()`. [#26075](https://github.com/ClickHouse/ClickHouse/pull/26075) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Add the `FIRST` keyword to the `ADD INDEX` command to be able to add the index at the beginning of the indices list. [#25904](https://github.com/ClickHouse/ClickHouse/pull/25904) ([xjewer](https://github.com/xjewer)).
|
||||
* Introduce `system.data_skipping_indices` table containing information about existing data skipping indices. Close [#7659](https://github.com/ClickHouse/ClickHouse/issues/7659). [#25693](https://github.com/ClickHouse/ClickHouse/pull/25693) ([Dmitry Novik](https://github.com/novikd)).
|
||||
* Add `bin`/`unbin` functions. [#25609](https://github.com/ClickHouse/ClickHouse/pull/25609) ([zhaoyu](https://github.com/zxc111)).
|
||||
* Support `Map` and `(U)Int128`, `U(Int256) types in `mapAdd` and `mapSubtract` functions. [#25596](https://github.com/ClickHouse/ClickHouse/pull/25596) ([Ildus Kurbangaliev](https://github.com/ildus)).
|
||||
* Support `DISTINCT ON (columns)` expression, close [#25404](https://github.com/ClickHouse/ClickHouse/issues/25404). [#25589](https://github.com/ClickHouse/ClickHouse/pull/25589) ([Zijie Lu](https://github.com/TszKitLo40)).
|
||||
* Add support for a part of SQLJSON standard. [#24148](https://github.com/ClickHouse/ClickHouse/pull/24148) ([l1tsolaiki](https://github.com/l1tsolaiki)).
|
||||
* Add MaterializedPostgreSQL table engine and database engine. This database engine allows replicating a whole database or any subset of database tables. [#20470](https://github.com/ClickHouse/ClickHouse/pull/20470) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Add an ability to reset a custom setting to default and remove it from the table's metadata. It allows rolling back the change without knowing the system/config's default. Closes [#14449](https://github.com/ClickHouse/ClickHouse/issues/14449). [#17769](https://github.com/ClickHouse/ClickHouse/pull/17769) ([xjewer](https://github.com/xjewer)).
|
||||
* Render pipelines as graphs in Web UI if `EXPLAIN PIPELINE graph = 1` query is submitted. [#26067](https://github.com/ClickHouse/ClickHouse/pull/26067) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
|
||||
#### Performance Improvements
|
||||
|
||||
* Compile aggregate functions. Use option `compile_aggregate_expressions` to enable it. [#24789](https://github.com/ClickHouse/ClickHouse/pull/24789) ([Maksim Kita](https://github.com/kitaisreal)).
|
||||
* Improve latency of short queries that require reading from tables with many columns. [#26371](https://github.com/ClickHouse/ClickHouse/pull/26371) ([Anton Popov](https://github.com/CurtizJ)).
|
||||
|
||||
#### Improvements
|
||||
|
||||
* Use `Map` data type for system logs tables (`system.query_log`, `system.query_thread_log`, `system.processes`, `system.opentelemetry_span_log`). These tables will be auto-created with new data types. Virtual columns are created to support old queries. Closes [#18698](https://github.com/ClickHouse/ClickHouse/issues/18698). [#23934](https://github.com/ClickHouse/ClickHouse/pull/23934), [#25773](https://github.com/ClickHouse/ClickHouse/pull/25773) ([hexiaoting](https://github.com/hexiaoting), [sundy-li](https://github.com/sundy-li)).
|
||||
* For a dictionary with a complex key containing only one attribute, allow not wrapping the key expression in tuple for functions `dictGet`, `dictHas`. [#26130](https://github.com/ClickHouse/ClickHouse/pull/26130) ([Maksim Kita](https://github.com/kitaisreal)).
|
||||
* Implement function `bin`/`hex` from `AggregateFunction` states. [#26094](https://github.com/ClickHouse/ClickHouse/pull/26094) ([zhaoyu](https://github.com/zxc111)).
|
||||
* Support arguments of `UUID` type for `empty` and `notEmpty` functions. `UUID` is empty if it is all zeros (nil UUID). Closes [#3446](https://github.com/ClickHouse/ClickHouse/issues/3446). [#25974](https://github.com/ClickHouse/ClickHouse/pull/25974) ([zhaoyu](https://github.com/zxc111)).
|
||||
* Fix error with query `SET SQL_SELECT_LIMIT` in MySQL protocol. Closes [#17115](https://github.com/ClickHouse/ClickHouse/issues/17115). [#25972](https://github.com/ClickHouse/ClickHouse/pull/25972) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* More instrumentation for network interaction: add counters for recv/send bytes; add gauges for recvs/sends. Added missing documentation. Close [#5897](https://github.com/ClickHouse/ClickHouse/issues/5897). [#25962](https://github.com/ClickHouse/ClickHouse/pull/25962) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Add setting `optimize_move_to_prewhere_if_final`. If query has `FINAL`, the optimization `move_to_prewhere` will be enabled only if both `optimize_move_to_prewhere` and `optimize_move_to_prewhere_if_final` are enabled. Closes [#8684](https://github.com/ClickHouse/ClickHouse/issues/8684). [#25940](https://github.com/ClickHouse/ClickHouse/pull/25940) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Allow complex quoted identifiers of JOINed tables. Close [#17861](https://github.com/ClickHouse/ClickHouse/issues/17861). [#25924](https://github.com/ClickHouse/ClickHouse/pull/25924) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Add support for Unicode (e.g. Chinese, Cyrillic) components in `Nested` data types. Close [#25594](https://github.com/ClickHouse/ClickHouse/issues/25594). [#25923](https://github.com/ClickHouse/ClickHouse/pull/25923) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Allow `quantiles*` functions to work with `aggregate_functions_null_for_empty`. Close [#25892](https://github.com/ClickHouse/ClickHouse/issues/25892). [#25919](https://github.com/ClickHouse/ClickHouse/pull/25919) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Allow parameters for parametric aggregate functions to be arbitrary constant expressions (e.g., `1 + 2`), not just literals. It also allows using the query parameters (in parameterized queries like `{param:UInt8}`) inside parametric aggregate functions. Closes [#11607](https://github.com/ClickHouse/ClickHouse/issues/11607). [#25910](https://github.com/ClickHouse/ClickHouse/pull/25910) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Correctly throw the exception on the attempt to parse an invalid `Date`. Closes [#6481](https://github.com/ClickHouse/ClickHouse/issues/6481). [#25909](https://github.com/ClickHouse/ClickHouse/pull/25909) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Support for multiple includes in configuration. It is possible to include users configuration, remote server configuration from multiple sources. Simply place `<include />` element with `from_zk`, `from_env` or `incl` attribute, and it will be replaced with the substitution. [#24404](https://github.com/ClickHouse/ClickHouse/pull/24404) ([nvartolomei](https://github.com/nvartolomei)).
|
||||
* Support for queries with a column named `"null"` (it must be specified in back-ticks or double quotes) and `ON CLUSTER`. Closes [#24035](https://github.com/ClickHouse/ClickHouse/issues/24035). [#25907](https://github.com/ClickHouse/ClickHouse/pull/25907) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Support `LowCardinality`, `Decimal`, and `UUID` for `JSONExtract`. Closes [#24606](https://github.com/ClickHouse/ClickHouse/issues/24606). [#25900](https://github.com/ClickHouse/ClickHouse/pull/25900) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Convert history file from `readline` format to `replxx` format. [#25888](https://github.com/ClickHouse/ClickHouse/pull/25888) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* Fix bug which can lead to intersecting parts after `DROP PART` or background deletion of an empty part. [#25884](https://github.com/ClickHouse/ClickHouse/pull/25884) ([alesapin](https://github.com/alesapin)).
|
||||
* Better handling of lost parts for `ReplicatedMergeTree` tables. Fixes rare inconsistencies in `ReplicationQueue`. Fixes [#10368](https://github.com/ClickHouse/ClickHouse/issues/10368). [#25820](https://github.com/ClickHouse/ClickHouse/pull/25820) ([alesapin](https://github.com/alesapin)).
|
||||
* Allow starting clickhouse-client with unreadable working directory. [#25817](https://github.com/ClickHouse/ClickHouse/pull/25817) ([ianton-ru](https://github.com/ianton-ru)).
|
||||
* Fix "No available columns" error for `Merge` storage. [#25801](https://github.com/ClickHouse/ClickHouse/pull/25801) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* MySQL Engine now supports the exchange of column comments between MySQL and ClickHouse. [#25795](https://github.com/ClickHouse/ClickHouse/pull/25795) ([Storozhuk Kostiantyn](https://github.com/sand6255)).
|
||||
* Fix inconsistent behaviour of `GROUP BY` constant on empty set. Closes [#6842](https://github.com/ClickHouse/ClickHouse/issues/6842). [#25786](https://github.com/ClickHouse/ClickHouse/pull/25786) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Cancel already running merges in partition on `DROP PARTITION` and `TRUNCATE` for `ReplicatedMergeTree`. Resolves [#17151](https://github.com/ClickHouse/ClickHouse/issues/17151). [#25684](https://github.com/ClickHouse/ClickHouse/pull/25684) ([tavplubix](https://github.com/tavplubix)).
|
||||
* Support ENUM` data type for MaterializeMySQL. [#25676](https://github.com/ClickHouse/ClickHouse/pull/25676) ([Storozhuk Kostiantyn](https://github.com/sand6255)).
|
||||
* Support materialized and aliased columns in JOIN, close [#13274](https://github.com/ClickHouse/ClickHouse/issues/13274). [#25634](https://github.com/ClickHouse/ClickHouse/pull/25634) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Fix possible logical race condition between `ALTER TABLE ... DETACH` and background merges. [#25605](https://github.com/ClickHouse/ClickHouse/pull/25605) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* Make `NetworkReceiveElapsedMicroseconds` metric to correctly include the time spent waiting for data from the client to `INSERT`. Close [#9958](https://github.com/ClickHouse/ClickHouse/issues/9958). [#25602](https://github.com/ClickHouse/ClickHouse/pull/25602) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Support `TRUNCATE TABLE` for StorageS3 and StorageHDFS. Close [#25530](https://github.com/ClickHouse/ClickHouse/issues/25530). [#25550](https://github.com/ClickHouse/ClickHouse/pull/25550) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Support for dynamic reloading of config to change number of threads in pool for background jobs execution (merges, mutations, fetches). [#25548](https://github.com/ClickHouse/ClickHouse/pull/25548) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
|
||||
* Allow extracting of non-string element as string using `JSONExtract`. This is for [#25414](https://github.com/ClickHouse/ClickHouse/issues/25414). [#25452](https://github.com/ClickHouse/ClickHouse/pull/25452) ([Amos Bird](https://github.com/amosbird)).
|
||||
* Support regular expression in `Database` argument for `StorageMerge`. Close [#776](https://github.com/ClickHouse/ClickHouse/issues/776). [#25064](https://github.com/ClickHouse/ClickHouse/pull/25064) ([flynn](https://github.com/ucasfl)).
|
||||
* Web UI: if the value looks like a URL, automatically generate a link. [#25965](https://github.com/ClickHouse/ClickHouse/pull/25965) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Make `sudo service clickhouse-server start` to work on systems with `systemd` like Centos 8. Close [#14298](https://github.com/ClickHouse/ClickHouse/issues/14298). Close [#17799](https://github.com/ClickHouse/ClickHouse/issues/17799). [#25921](https://github.com/ClickHouse/ClickHouse/pull/25921) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Fix incorrect `SET ROLE` in some cases. [#26707](https://github.com/ClickHouse/ClickHouse/pull/26707) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Fix potential `nullptr` dereference in window functions. Fix [#25276](https://github.com/ClickHouse/ClickHouse/issues/25276). [#26668](https://github.com/ClickHouse/ClickHouse/pull/26668) ([Alexander Kuzmenkov](https://github.com/akuzm)).
|
||||
* Fix incorrect function names of `groupBitmapAnd/Or/Xor`. Fix [#26557](https://github.com/ClickHouse/ClickHouse/pull/26557) ([Amos Bird](https://github.com/amosbird)).
|
||||
* Fix crash in rabbitmq shutdown in case rabbitmq setup was not started. Closes [#26504](https://github.com/ClickHouse/ClickHouse/issues/26504). [#26529](https://github.com/ClickHouse/ClickHouse/pull/26529) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Fix issues with `CREATE DICTIONARY` query if dictionary name or database name was quoted. Closes [#26491](https://github.com/ClickHouse/ClickHouse/issues/26491). [#26508](https://github.com/ClickHouse/ClickHouse/pull/26508) ([Maksim Kita](https://github.com/kitaisreal)).
|
||||
* Fix broken name resolution after rewriting column aliases. Fix [#26432](https://github.com/ClickHouse/ClickHouse/issues/26432). [#26475](https://github.com/ClickHouse/ClickHouse/pull/26475) ([Amos Bird](https://github.com/amosbird)).
|
||||
* Fix infinite non-joined block stream in `partial_merge_join` close [#26325](https://github.com/ClickHouse/ClickHouse/issues/26325). [#26374](https://github.com/ClickHouse/ClickHouse/pull/26374) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Fix possible crash when login as dropped user. Fix [#26073](https://github.com/ClickHouse/ClickHouse/issues/26073). [#26363](https://github.com/ClickHouse/ClickHouse/pull/26363) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Fix `optimize_distributed_group_by_sharding_key` for multiple columns (leads to incorrect result w/ `optimize_skip_unused_shards=1`/`allow_nondeterministic_optimize_skip_unused_shards=1` and multiple columns in sharding key expression). [#26353](https://github.com/ClickHouse/ClickHouse/pull/26353) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* `CAST` from `Date` to `DateTime` (or `DateTime64`) was not using the timezone of the `DateTime` type. It can also affect the comparison between `Date` and `DateTime`. Inference of the common type for `Date` and `DateTime` also was not using the corresponding timezone. It affected the results of function `if` and array construction. Closes [#24128](https://github.com/ClickHouse/ClickHouse/issues/24128). [#24129](https://github.com/ClickHouse/ClickHouse/pull/24129) ([Maksim Kita](https://github.com/kitaisreal)).
|
||||
* Fixed rare bug in lost replica recovery that may cause replicas to diverge. [#26321](https://github.com/ClickHouse/ClickHouse/pull/26321) ([tavplubix](https://github.com/tavplubix)).
|
||||
* Fix zstd decompression in case there are escape sequences at the end of internal buffer. Closes [#26013](https://github.com/ClickHouse/ClickHouse/issues/26013). [#26314](https://github.com/ClickHouse/ClickHouse/pull/26314) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Fix logical error on join with totals, close [#26017](https://github.com/ClickHouse/ClickHouse/issues/26017). [#26250](https://github.com/ClickHouse/ClickHouse/pull/26250) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Remove excessive newline in `thread_name` column in `system.stack_trace` table. Fix [#24124](https://github.com/ClickHouse/ClickHouse/issues/24124). [#26210](https://github.com/ClickHouse/ClickHouse/pull/26210) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Fix `joinGet` with `LowCarinality` columns, close [#25993](https://github.com/ClickHouse/ClickHouse/issues/25993). [#26118](https://github.com/ClickHouse/ClickHouse/pull/26118) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Fix possible crash in `pointInPolygon` if the setting `validate_polygons` is turned off. [#26113](https://github.com/ClickHouse/ClickHouse/pull/26113) ([alexey-milovidov](https://github.com/alexey-milovidov)).
|
||||
* Fix throwing exception when iterate over non-existing remote directory. [#26087](https://github.com/ClickHouse/ClickHouse/pull/26087) ([ianton-ru](https://github.com/ianton-ru)).
|
||||
* Fix rare server crash because of `abort` in ZooKeeper client. Fixes [#25813](https://github.com/ClickHouse/ClickHouse/issues/25813). [#26079](https://github.com/ClickHouse/ClickHouse/pull/26079) ([alesapin](https://github.com/alesapin)).
|
||||
* Fix wrong thread estimation for right subquery join in some cases. Close [#24075](https://github.com/ClickHouse/ClickHouse/issues/24075). [#26052](https://github.com/ClickHouse/ClickHouse/pull/26052) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Fixed incorrect `sequence_id` in MySQL protocol packets that ClickHouse sends on exception during query execution. It might cause MySQL client to reset connection to ClickHouse server. Fixes [#21184](https://github.com/ClickHouse/ClickHouse/issues/21184). [#26051](https://github.com/ClickHouse/ClickHouse/pull/26051) ([tavplubix](https://github.com/tavplubix)).
|
||||
* Fix possible mismatched header when using normal projection with `PREWHERE`. Fix [#26020](https://github.com/ClickHouse/ClickHouse/issues/26020). [#26038](https://github.com/ClickHouse/ClickHouse/pull/26038) ([Amos Bird](https://github.com/amosbird)).
|
||||
* Fix formatting of type `Map` with integer keys to `JSON`. [#25982](https://github.com/ClickHouse/ClickHouse/pull/25982) ([Anton Popov](https://github.com/CurtizJ)).
|
||||
* Fix possible deadlock during query profiler stack unwinding. Fix [#25968](https://github.com/ClickHouse/ClickHouse/issues/25968). [#25970](https://github.com/ClickHouse/ClickHouse/pull/25970) ([Maksim Kita](https://github.com/kitaisreal)).
|
||||
* Fix crash on call `dictGet()` with bad arguments. [#25913](https://github.com/ClickHouse/ClickHouse/pull/25913) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
* Fixed `scram-sha-256` authentication for PostgreSQL engines. Closes [#24516](https://github.com/ClickHouse/ClickHouse/issues/24516). [#25906](https://github.com/ClickHouse/ClickHouse/pull/25906) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Fix extremely long backoff for background tasks when the background pool is full. Fixes [#25836](https://github.com/ClickHouse/ClickHouse/issues/25836). [#25893](https://github.com/ClickHouse/ClickHouse/pull/25893) ([alesapin](https://github.com/alesapin)).
|
||||
* Fix ARM exception handling with non default page size. Fixes [#25512](https://github.com/ClickHouse/ClickHouse/issues/25512), [#25044](https://github.com/ClickHouse/ClickHouse/issues/25044), [#24901](https://github.com/ClickHouse/ClickHouse/issues/24901), [#23183](https://github.com/ClickHouse/ClickHouse/issues/23183), [#20221](https://github.com/ClickHouse/ClickHouse/issues/20221), [#19703](https://github.com/ClickHouse/ClickHouse/issues/19703), [#19028](https://github.com/ClickHouse/ClickHouse/issues/19028), [#18391](https://github.com/ClickHouse/ClickHouse/issues/18391), [#18121](https://github.com/ClickHouse/ClickHouse/issues/18121), [#17994](https://github.com/ClickHouse/ClickHouse/issues/17994), [#12483](https://github.com/ClickHouse/ClickHouse/issues/12483). [#25854](https://github.com/ClickHouse/ClickHouse/pull/25854) ([Maksim Kita](https://github.com/kitaisreal)).
|
||||
* Fix sharding_key from column w/o function for `remote()` (before `select * from remote('127.1', system.one, dummy)` leads to `Unknown column: dummy, there are only columns .` error). [#25824](https://github.com/ClickHouse/ClickHouse/pull/25824) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* Fixed `Not found column ...` and `Missing column ...` errors when selecting from `MaterializeMySQL`. Fixes [#23708](https://github.com/ClickHouse/ClickHouse/issues/23708), [#24830](https://github.com/ClickHouse/ClickHouse/issues/24830), [#25794](https://github.com/ClickHouse/ClickHouse/issues/25794). [#25822](https://github.com/ClickHouse/ClickHouse/pull/25822) ([tavplubix](https://github.com/tavplubix)).
|
||||
* Fix `optimize_skip_unused_shards_rewrite_in` for non-UInt64 types (may select incorrect shards eventually or throw `Cannot infer type of an empty tuple` or `Function tuple requires at least one argument`). [#25798](https://github.com/ClickHouse/ClickHouse/pull/25798) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* Fix rare bug with `DROP PART` query for `ReplicatedMergeTree` tables which can lead to error message `Unexpected merged part intersecting drop range`. [#25783](https://github.com/ClickHouse/ClickHouse/pull/25783) ([alesapin](https://github.com/alesapin)).
|
||||
* Fix bug in `TTL` with `GROUP BY` expression which refuses to execute `TTL` after first execution in part. [#25743](https://github.com/ClickHouse/ClickHouse/pull/25743) ([alesapin](https://github.com/alesapin)).
|
||||
* Allow StorageMerge to access tables with aliases. Closes [#6051](https://github.com/ClickHouse/ClickHouse/issues/6051). [#25694](https://github.com/ClickHouse/ClickHouse/pull/25694) ([Kseniia Sumarokova](https://github.com/kssenii)).
|
||||
* Fix slow dict join in some cases, close [#24209](https://github.com/ClickHouse/ClickHouse/issues/24209). [#25618](https://github.com/ClickHouse/ClickHouse/pull/25618) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Fix `ALTER MODIFY COLUMN` of columns, which participates in TTL expressions. [#25554](https://github.com/ClickHouse/ClickHouse/pull/25554) ([Anton Popov](https://github.com/CurtizJ)).
|
||||
* Fix assertion in `PREWHERE` with non-UInt8 type, close [#19589](https://github.com/ClickHouse/ClickHouse/issues/19589). [#25484](https://github.com/ClickHouse/ClickHouse/pull/25484) ([Vladimir C](https://github.com/vdimir)).
|
||||
* Fix some fuzzed msan crash. Fixes [#22517](https://github.com/ClickHouse/ClickHouse/issues/22517). [#26428](https://github.com/ClickHouse/ClickHouse/pull/26428) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
|
||||
* Fix empty history file conversion. [#26589](https://github.com/ClickHouse/ClickHouse/pull/26589) ([Azat Khuzhin](https://github.com/azat)).
|
||||
* Update `chown` cmd check in `clickhouse-server` docker entrypoint. It fixes error 'cluster pod restart failed (or timeout)' on kubernetes. [#26545](https://github.com/ClickHouse/ClickHouse/pull/26545) ([Ky Li](https://github.com/Kylinrix)).
|
||||
|
||||
#### Build/Testing/Packaging Improvements
|
||||
|
||||
* Disabling TestFlows LDAP module due to test fails. [#26065](https://github.com/ClickHouse/ClickHouse/pull/26065) ([vzakaznikov](https://github.com/vzakaznikov)).
|
||||
* Enabling all TestFlows modules and fixing some tests. [#26011](https://github.com/ClickHouse/ClickHouse/pull/26011) ([vzakaznikov](https://github.com/vzakaznikov)).
|
||||
* Add new tests for checking access rights for columns used in filters (`WHERE` / `PREWHERE` / row policy) of the `SELECT` statement after changes in [#24405](https://github.com/ClickHouse/ClickHouse/pull/24405). [#25619](https://github.com/ClickHouse/ClickHouse/pull/25619) ([Vitaly Baranov](https://github.com/vitlibar)).
|
||||
|
||||
#### Other
|
||||
|
||||
* Add `clickhouse-keeper-converter` tool which allows converting zookeeper logs and snapshots into `clickhouse-keeper` snapshot format. [#25428](https://github.com/ClickHouse/ClickHouse/pull/25428) ([alesapin](https://github.com/alesapin)).
|
||||
|
||||
|
||||
|
||||
### ClickHouse release v21.7, 2021-07-09
|
||||
|
||||
#### Backward Incompatible Change
|
||||
|
@ -271,12 +271,6 @@ endif()
|
||||
|
||||
include(cmake/cpu_features.cmake)
|
||||
|
||||
option(ARCH_NATIVE "Add -march=native compiler flag. This makes your binaries non-portable but more performant code may be generated.")
|
||||
|
||||
if (ARCH_NATIVE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||
endif ()
|
||||
|
||||
# Asynchronous unwind tables are needed for Query Profiler.
|
||||
# They are already by default on some platforms but possibly not on all platforms.
|
||||
# Enable it explicitly.
|
||||
|
@ -60,6 +60,7 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
||||
offset_at_start_of_epoch = cctz_time_zone.lookup(cctz_time_zone.lookup(epoch).pre).offset;
|
||||
offset_at_start_of_lut = cctz_time_zone.lookup(cctz_time_zone.lookup(lut_start).pre).offset;
|
||||
offset_is_whole_number_of_hours_during_epoch = true;
|
||||
offset_is_whole_number_of_minutes_during_epoch = true;
|
||||
|
||||
cctz::civil_day date = lut_start;
|
||||
|
||||
@ -108,6 +109,9 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
||||
if (offset_is_whole_number_of_hours_during_epoch && start_of_day > 0 && start_of_day % 3600)
|
||||
offset_is_whole_number_of_hours_during_epoch = false;
|
||||
|
||||
if (offset_is_whole_number_of_minutes_during_epoch && start_of_day > 0 && start_of_day % 60)
|
||||
offset_is_whole_number_of_minutes_during_epoch = false;
|
||||
|
||||
/// If UTC offset was changed this day.
|
||||
/// Change in time zone without transition is possible, e.g. Moscow 1991 Sun, 31 Mar, 02:00 MSK to EEST
|
||||
cctz::time_zone::civil_transition transition{};
|
||||
|
@ -193,6 +193,7 @@ private:
|
||||
/// UTC offset at the beginning of the first supported year.
|
||||
Time offset_at_start_of_lut;
|
||||
bool offset_is_whole_number_of_hours_during_epoch;
|
||||
bool offset_is_whole_number_of_minutes_during_epoch;
|
||||
|
||||
/// Time zone name.
|
||||
std::string time_zone;
|
||||
@ -251,18 +252,23 @@ private:
|
||||
}
|
||||
|
||||
template <typename T, typename Divisor>
|
||||
static inline T roundDown(T x, Divisor divisor)
|
||||
inline T roundDown(T x, Divisor divisor) const
|
||||
{
|
||||
static_assert(std::is_integral_v<T> && std::is_integral_v<Divisor>);
|
||||
assert(divisor > 0);
|
||||
|
||||
if (likely(x >= 0))
|
||||
return x / divisor * divisor;
|
||||
if (likely(offset_is_whole_number_of_hours_during_epoch))
|
||||
{
|
||||
if (likely(x >= 0))
|
||||
return x / divisor * divisor;
|
||||
|
||||
/// Integer division for negative numbers rounds them towards zero (up).
|
||||
/// We will shift the number so it will be rounded towards -inf (down).
|
||||
/// Integer division for negative numbers rounds them towards zero (up).
|
||||
/// We will shift the number so it will be rounded towards -inf (down).
|
||||
return (x + 1 - divisor) / divisor * divisor;
|
||||
}
|
||||
|
||||
return (x + 1 - divisor) / divisor * divisor;
|
||||
Time date = find(x).date;
|
||||
return date + (x - date) / divisor * divisor;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -459,10 +465,21 @@ public:
|
||||
|
||||
inline unsigned toSecond(Time t) const
|
||||
{
|
||||
auto res = t % 60;
|
||||
if (likely(res >= 0))
|
||||
return res;
|
||||
return res + 60;
|
||||
if (likely(offset_is_whole_number_of_minutes_during_epoch))
|
||||
{
|
||||
Time res = t % 60;
|
||||
if (likely(res >= 0))
|
||||
return res;
|
||||
return res + 60;
|
||||
}
|
||||
|
||||
LUTIndex index = findIndex(t);
|
||||
Time time = t - lut[index].date;
|
||||
|
||||
if (time >= lut[index].time_at_offset_change())
|
||||
time += lut[index].amount_of_offset_change();
|
||||
|
||||
return time % 60;
|
||||
}
|
||||
|
||||
inline unsigned toMinute(Time t) const
|
||||
@ -483,29 +500,11 @@ public:
|
||||
}
|
||||
|
||||
/// NOTE: Assuming timezone offset is a multiple of 15 minutes.
|
||||
inline Time toStartOfMinute(Time t) const { return roundDown(t, 60); }
|
||||
inline Time toStartOfFiveMinute(Time t) const { return roundDown(t, 300); }
|
||||
inline Time toStartOfFifteenMinutes(Time t) const { return roundDown(t, 900); }
|
||||
|
||||
inline Time toStartOfTenMinutes(Time t) const
|
||||
{
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return t / 600 * 600;
|
||||
|
||||
/// More complex logic is for Nepal - it has offset 05:45. Australia/Eucla is also unfortunate.
|
||||
Time date = find(t).date;
|
||||
return date + (t - date) / 600 * 600;
|
||||
}
|
||||
|
||||
/// NOTE: Assuming timezone transitions are multiple of hours. Lord Howe Island in Australia is a notable exception.
|
||||
inline Time toStartOfHour(Time t) const
|
||||
{
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return t / 3600 * 3600;
|
||||
|
||||
Time date = find(t).date;
|
||||
return date + (t - date) / 3600 * 3600;
|
||||
}
|
||||
inline Time toStartOfMinute(Time t) const { return toStartOfMinuteInterval(t, 1); }
|
||||
inline Time toStartOfFiveMinute(Time t) const { return toStartOfMinuteInterval(t, 5); }
|
||||
inline Time toStartOfFifteenMinutes(Time t) const { return toStartOfMinuteInterval(t, 15); }
|
||||
inline Time toStartOfTenMinutes(Time t) const { return toStartOfMinuteInterval(t, 10); }
|
||||
inline Time toStartOfHour(Time t) const { return roundDown(t, 3600); }
|
||||
|
||||
/** Number of calendar day since the beginning of UNIX epoch (1970-01-01 is zero)
|
||||
* We use just two bytes for it. It covers the range up to 2105 and slightly more.
|
||||
@ -903,25 +902,24 @@ public:
|
||||
|
||||
inline Time toStartOfMinuteInterval(Time t, UInt64 minutes) const
|
||||
{
|
||||
if (minutes == 1)
|
||||
return toStartOfMinute(t);
|
||||
UInt64 divisor = 60 * minutes;
|
||||
if (likely(offset_is_whole_number_of_minutes_during_epoch))
|
||||
{
|
||||
if (likely(t >= 0))
|
||||
return t / divisor * divisor;
|
||||
return (t + 1 - divisor) / divisor * divisor;
|
||||
}
|
||||
|
||||
/** In contrast to "toStartOfHourInterval" function above,
|
||||
* the minute intervals are not aligned to the midnight.
|
||||
* You will get unexpected results if for example, you round down to 60 minute interval
|
||||
* and there was a time shift to 30 minutes.
|
||||
*
|
||||
* But this is not specified in docs and can be changed in future.
|
||||
*/
|
||||
|
||||
UInt64 seconds = 60 * minutes;
|
||||
return roundDown(t, seconds);
|
||||
Time date = find(t).date;
|
||||
return date + (t - date) / divisor * divisor;
|
||||
}
|
||||
|
||||
inline Time toStartOfSecondInterval(Time t, UInt64 seconds) const
|
||||
{
|
||||
if (seconds == 1)
|
||||
return t;
|
||||
if (seconds % 60 == 0)
|
||||
return toStartOfMinuteInterval(t, seconds / 60);
|
||||
|
||||
return roundDown(t, seconds);
|
||||
}
|
||||
|
@ -5,109 +5,128 @@ include (CMakePushCheckState)
|
||||
|
||||
cmake_push_check_state ()
|
||||
|
||||
# gcc -dM -E -mno-sse2 - < /dev/null | sort > gcc-dump-nosse2
|
||||
# gcc -dM -E -msse2 - < /dev/null | sort > gcc-dump-sse2
|
||||
#define __SSE2__ 1
|
||||
#define __SSE2_MATH__ 1
|
||||
# The variables HAVE_* determine if compiler has support for the flag to use the corresponding instruction set.
|
||||
# The options ENABLE_* determine if we will tell compiler to actually use the corresponding instruction set if compiler can do it.
|
||||
|
||||
# gcc -dM -E -msse4.1 - < /dev/null | sort > gcc-dump-sse41
|
||||
#define __SSE4_1__ 1
|
||||
# All of them are unrelated to the instruction set at the host machine
|
||||
# (you can compile for newer instruction set on old machines and vice versa).
|
||||
|
||||
set (TEST_FLAG "-msse4.1")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <smmintrin.h>
|
||||
int main() {
|
||||
auto a = _mm_insert_epi8(__m128i(), 0, 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SSE41)
|
||||
if (HAVE_SSE41)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
option (ENABLE_SSSE3 "Use SSSE3 instructions on x86_64" 1)
|
||||
option (ENABLE_SSE41 "Use SSE4.1 instructions on x86_64" 1)
|
||||
option (ENABLE_SSE42 "Use SSE4.2 instructions on x86_64" 1)
|
||||
option (ENABLE_PCLMULQDQ "Use pclmulqdq instructions on x86_64" 1)
|
||||
option (ENABLE_POPCNT "Use popcnt instructions on x86_64" 1)
|
||||
option (ENABLE_AVX "Use AVX instructions on x86_64" 0)
|
||||
option (ENABLE_AVX2 "Use AVX2 instructions on x86_64" 0)
|
||||
|
||||
if (ARCH_PPC64LE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -maltivec -D__SSE2__=1 -DNO_WARN_X86_INTRINSICS")
|
||||
endif ()
|
||||
option (ARCH_NATIVE "Add -march=native compiler flag. This makes your binaries non-portable but more performant code may be generated. This option overrides ENABLE_* options for specific instruction set. Highly not recommended to use." 0)
|
||||
|
||||
# gcc -dM -E -msse4.2 - < /dev/null | sort > gcc-dump-sse42
|
||||
#define __SSE4_2__ 1
|
||||
if (ARCH_NATIVE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||
|
||||
set (TEST_FLAG "-msse4.2")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <nmmintrin.h>
|
||||
int main() {
|
||||
auto a = _mm_crc32_u64(0, 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SSE42)
|
||||
if (HAVE_SSE42)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
else ()
|
||||
set (TEST_FLAG "-mssse3")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <tmmintrin.h>
|
||||
int main() {
|
||||
__m64 a = _mm_abs_pi8(__m64());
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SSSE3)
|
||||
if (HAVE_SSSE3 AND ENABLE_SSSE3)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
|
||||
set (TEST_FLAG "-mssse3")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <tmmintrin.h>
|
||||
int main() {
|
||||
__m64 a = _mm_abs_pi8(__m64());
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SSSE3)
|
||||
|
||||
set (TEST_FLAG "-mavx")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <immintrin.h>
|
||||
int main() {
|
||||
auto a = _mm256_insert_epi8(__m256i(), 0, 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_AVX)
|
||||
set (TEST_FLAG "-msse4.1")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <smmintrin.h>
|
||||
int main() {
|
||||
auto a = _mm_insert_epi8(__m128i(), 0, 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SSE41)
|
||||
if (HAVE_SSE41 AND ENABLE_SSE41)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
|
||||
set (TEST_FLAG "-mavx2")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <immintrin.h>
|
||||
int main() {
|
||||
auto a = _mm256_add_epi16(__m256i(), __m256i());
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_AVX2)
|
||||
if (ARCH_PPC64LE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -maltivec -D__SSE2__=1 -DNO_WARN_X86_INTRINSICS")
|
||||
endif ()
|
||||
|
||||
set (TEST_FLAG "-mpclmul")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <wmmintrin.h>
|
||||
int main() {
|
||||
auto a = _mm_clmulepi64_si128(__m128i(), __m128i(), 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_PCLMULQDQ)
|
||||
set (TEST_FLAG "-msse4.2")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <nmmintrin.h>
|
||||
int main() {
|
||||
auto a = _mm_crc32_u64(0, 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SSE42)
|
||||
if (HAVE_SSE42 AND ENABLE_SSE42)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
|
||||
# gcc -dM -E -mpopcnt - < /dev/null | sort > gcc-dump-popcnt
|
||||
#define __POPCNT__ 1
|
||||
set (TEST_FLAG "-mpclmul")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <wmmintrin.h>
|
||||
int main() {
|
||||
auto a = _mm_clmulepi64_si128(__m128i(), __m128i(), 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_PCLMULQDQ)
|
||||
if (HAVE_PCLMULQDQ AND ENABLE_PCLMULQDQ)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
|
||||
set (TEST_FLAG "-mpopcnt")
|
||||
set (TEST_FLAG "-mpopcnt")
|
||||
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
int main() {
|
||||
auto a = __builtin_popcountll(0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_POPCNT)
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
int main() {
|
||||
auto a = __builtin_popcountll(0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_POPCNT)
|
||||
if (HAVE_POPCNT AND ENABLE_POPCNT)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
|
||||
if (HAVE_POPCNT AND NOT ARCH_AARCH64)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
set (TEST_FLAG "-mavx")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <immintrin.h>
|
||||
int main() {
|
||||
auto a = _mm256_insert_epi8(__m256i(), 0, 0);
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_AVX)
|
||||
if (HAVE_AVX AND ENABLE_AVX)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
|
||||
set (TEST_FLAG "-mavx2")
|
||||
set (CMAKE_REQUIRED_FLAGS "${TEST_FLAG} -O0")
|
||||
check_cxx_source_compiles("
|
||||
#include <immintrin.h>
|
||||
int main() {
|
||||
auto a = _mm256_add_epi16(__m256i(), __m256i());
|
||||
(void)a;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_AVX2)
|
||||
if (HAVE_AVX2 AND ENABLE_AVX2)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${TEST_FLAG}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
cmake_pop_check_state ()
|
||||
|
@ -26,17 +26,14 @@ target_include_directories(roaring SYSTEM BEFORE PUBLIC "${LIBRARY_DIR}/include"
|
||||
target_include_directories(roaring SYSTEM BEFORE PUBLIC "${LIBRARY_DIR}/cpp")
|
||||
|
||||
# We redirect malloc/free family of functions to different functions that will track memory in ClickHouse.
|
||||
# It will make this library depend on linking to 'clickhouse_common_io' library that is not done explicitly via 'target_link_libraries'.
|
||||
# And we check that all libraries dependencies are satisfied and all symbols are resolved if we do build with shared libraries.
|
||||
# That's why we enable it only in static build.
|
||||
# Also note that we exploit implicit function declarations.
|
||||
|
||||
if (USE_STATIC_LIBRARIES)
|
||||
target_compile_definitions(roaring PRIVATE
|
||||
target_compile_definitions(roaring PRIVATE
|
||||
-Dmalloc=clickhouse_malloc
|
||||
-Dcalloc=clickhouse_calloc
|
||||
-Drealloc=clickhouse_realloc
|
||||
-Dreallocarray=clickhouse_reallocarray
|
||||
-Dfree=clickhouse_free
|
||||
-Dposix_memalign=clickhouse_posix_memalign)
|
||||
endif ()
|
||||
|
||||
target_link_libraries(roaring PUBLIC clickhouse_common_io)
|
||||
|
@ -4,3 +4,6 @@ set(SIMDJSON_SRC "${SIMDJSON_SRC_DIR}/simdjson.cpp")
|
||||
|
||||
add_library(simdjson ${SIMDJSON_SRC})
|
||||
target_include_directories(simdjson SYSTEM PUBLIC "${SIMDJSON_INCLUDE_DIR}" PRIVATE "${SIMDJSON_SRC_DIR}")
|
||||
|
||||
# simdjson is using its own CPU dispatching and get confused if we enable AVX/AVX2 flags.
|
||||
target_compile_options(simdjson PRIVATE -mno-avx -mno-avx2)
|
||||
|
@ -155,6 +155,10 @@ Normally ClickHouse is statically linked into a single static `clickhouse` binar
|
||||
-DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1
|
||||
```
|
||||
|
||||
Note that in this configuration there is no single `clickhouse` binary, and you have to run `clickhouse-server`, `clickhouse-client` etc.
|
||||
Note that the split build has several drawbacks:
|
||||
* There is no single `clickhouse` binary, and you have to run `clickhouse-server`, `clickhouse-client`, etc.
|
||||
* Risk of segfault if you run any of the programs while rebuilding the project.
|
||||
* You cannot run the integration tests since they only work a single complete binary.
|
||||
* You can't easily copy the binaries elsewhere. Instead of moving a single binary you'll need to copy all binaries and libraries.
|
||||
|
||||
[Original article](https://clickhouse.tech/docs/en/development/build/) <!--hide-->
|
||||
|
@ -1,3 +1,6 @@
|
||||
#include <string>
|
||||
#include "Common/MemoryTracker.h"
|
||||
#include "Columns/ColumnsNumber.h"
|
||||
#include "ConnectionParameters.h"
|
||||
#include "QueryFuzzer.h"
|
||||
#include "Suggest.h"
|
||||
@ -100,6 +103,14 @@
|
||||
#pragma GCC optimize("-fno-var-tracking-assignments")
|
||||
#endif
|
||||
|
||||
namespace CurrentMetrics
|
||||
{
|
||||
extern const Metric Revision;
|
||||
extern const Metric VersionInteger;
|
||||
extern const Metric MemoryTracking;
|
||||
extern const Metric MaxDDLEntryID;
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace DB
|
||||
@ -524,6 +535,18 @@ private:
|
||||
{
|
||||
UseSSL use_ssl;
|
||||
|
||||
MainThreadStatus::getInstance();
|
||||
|
||||
/// Limit on total memory usage
|
||||
size_t max_client_memory_usage = config().getInt64("max_memory_usage_in_client", 0 /*default value*/);
|
||||
|
||||
if (max_client_memory_usage != 0)
|
||||
{
|
||||
total_memory_tracker.setHardLimit(max_client_memory_usage);
|
||||
total_memory_tracker.setDescription("(total)");
|
||||
total_memory_tracker.setMetric(CurrentMetrics::MemoryTracking);
|
||||
}
|
||||
|
||||
registerFormats();
|
||||
registerFunctions();
|
||||
registerAggregateFunctions();
|
||||
@ -2581,6 +2604,7 @@ public:
|
||||
("opentelemetry-tracestate", po::value<std::string>(), "OpenTelemetry tracestate header as described by W3C Trace Context recommendation")
|
||||
("history_file", po::value<std::string>(), "path to history file")
|
||||
("no-warnings", "disable warnings when client connects to server")
|
||||
("max_memory_usage_in_client", po::value<int>(), "sets memory limit in client")
|
||||
;
|
||||
|
||||
Settings cmd_settings;
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <pcg-random/pcg_random.hpp>
|
||||
|
||||
#include <Common/randomSeed.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <Core/Field.h>
|
||||
#include <Parsers/IAST.h>
|
||||
|
||||
|
@ -126,6 +126,7 @@ namespace CurrentMetrics
|
||||
extern const Metric VersionInteger;
|
||||
extern const Metric MemoryTracking;
|
||||
extern const Metric MaxDDLEntryID;
|
||||
extern const Metric MaxPushedDDLEntryID;
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
@ -1468,7 +1469,8 @@ if (ThreadFuzzer::instance().isEffective())
|
||||
if (pool_size < 1)
|
||||
throw Exception("distributed_ddl.pool_size should be greater then 0", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
|
||||
global_context->setDDLWorker(std::make_unique<DDLWorker>(pool_size, ddl_zookeeper_path, global_context, &config(),
|
||||
"distributed_ddl", "DDLWorker", &CurrentMetrics::MaxDDLEntryID));
|
||||
"distributed_ddl", "DDLWorker",
|
||||
&CurrentMetrics::MaxDDLEntryID, &CurrentMetrics::MaxPushedDDLEntryID));
|
||||
}
|
||||
|
||||
for (auto & server : *servers)
|
||||
|
@ -455,7 +455,7 @@ UUID IAccessStorage::login(
|
||||
if (!replace_exception_with_cannot_authenticate)
|
||||
throw;
|
||||
|
||||
tryLogCurrentException(getLogger(), credentials.getUserName() + ": Authentication failed");
|
||||
tryLogCurrentException(getLogger(), "from: " + address.toString() + ", user: " + credentials.getUserName() + ": Authentication failed");
|
||||
throwCannotAuthenticate(credentials.getUserName());
|
||||
}
|
||||
}
|
||||
|
@ -299,10 +299,11 @@ target_link_libraries(clickhouse_common_io
|
||||
${ZLIB_LIBRARIES}
|
||||
pcg_random
|
||||
Poco::Foundation
|
||||
roaring
|
||||
)
|
||||
|
||||
|
||||
# Make dbms depend on roaring instead of clickhouse_common_io so that roaring itself can depend on clickhouse_common_io
|
||||
# That way we we can redirect malloc/free functions avoiding circular dependencies
|
||||
dbms_target_link_libraries(PUBLIC roaring)
|
||||
|
||||
if (USE_RDKAFKA)
|
||||
dbms_target_link_libraries(PRIVATE ${CPPKAFKA_LIBRARY} ${RDKAFKA_LIBRARY})
|
||||
|
@ -187,6 +187,7 @@ public:
|
||||
* So LC(Nullable(T)) would return true, LC(U) -- false.
|
||||
*/
|
||||
bool nestedIsNullable() const { return isColumnNullable(*dictionary.getColumnUnique().getNestedColumn()); }
|
||||
bool nestedCanBeInsideNullable() const { return dictionary.getColumnUnique().getNestedColumn()->canBeInsideNullable(); }
|
||||
void nestedToNullable() { dictionary.getColumnUnique().nestedToNullable(); }
|
||||
void nestedRemoveNullable() { dictionary.getColumnUnique().nestedRemoveNullable(); }
|
||||
|
||||
|
@ -60,6 +60,7 @@
|
||||
M(BrokenDistributedFilesToInsert, "Number of files for asynchronous insertion into Distributed tables that has been marked as broken. This metric will starts from 0 on start. Number of files for every shard is summed.") \
|
||||
M(TablesToDropQueueSize, "Number of dropped tables, that are waiting for background data removal.") \
|
||||
M(MaxDDLEntryID, "Max processed DDL entry of DDLWorker.") \
|
||||
M(MaxPushedDDLEntryID, "Max DDL entry of DDLWorker that pushed to zookeeper.") \
|
||||
M(PartsTemporary, "The part is generating now, it is not in data_parts list.") \
|
||||
M(PartsPreCommitted, "The part is in data_parts, but not used for SELECTs.") \
|
||||
M(PartsCommitted, "Active data part, used by current and upcoming SELECTs.") \
|
||||
|
@ -183,9 +183,6 @@ void MemoryTracker::allocImpl(Int64 size, bool throw_if_memory_exceeded)
|
||||
std::bernoulli_distribution fault(fault_probability);
|
||||
if (unlikely(fault_probability && fault(thread_local_rng)) && memoryTrackerCanThrow(level, true) && throw_if_memory_exceeded)
|
||||
{
|
||||
ProfileEvents::increment(ProfileEvents::QueryMemoryLimitExceeded);
|
||||
amount.fetch_sub(size, std::memory_order_relaxed);
|
||||
|
||||
/// Prevent recursion. Exception::ctor -> std::string -> new[] -> MemoryTracker::alloc
|
||||
BlockerInThread untrack_lock(VariableContext::Global);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <Coordination/KeeperStorageDispatcher.h>
|
||||
#include <Common/setThreadName.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <Common/ZooKeeper/KeeperException.h>
|
||||
#include <future>
|
||||
#include <chrono>
|
||||
|
@ -31,6 +31,10 @@ SRCS(
|
||||
MySQL/PacketsProtocolText.cpp
|
||||
MySQL/PacketsReplication.cpp
|
||||
NamesAndTypes.cpp
|
||||
PostgreSQL/Connection.cpp
|
||||
PostgreSQL/PoolWithFailover.cpp
|
||||
PostgreSQL/Utils.cpp
|
||||
PostgreSQL/insertPostgreSQLValue.cpp
|
||||
PostgreSQLProtocol.cpp
|
||||
QueryProcessingStage.cpp
|
||||
Settings.cpp
|
||||
|
@ -3,7 +3,8 @@
|
||||
#include <Poco/Timespan.h>
|
||||
#include <common/types.h>
|
||||
#include <DataStreams/SizeLimits.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
|
||||
class Stopwatch;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ void PostgreSQLSource<T>::init(const Block & sample_block)
|
||||
template<typename T>
|
||||
void PostgreSQLSource<T>::onStart()
|
||||
{
|
||||
if (connection_holder)
|
||||
if (!tx)
|
||||
tx = std::make_shared<T>(connection_holder->get());
|
||||
|
||||
stream = std::make_unique<pqxx::stream_from>(*tx, pqxx::from_query, std::string_view(query_str));
|
||||
|
@ -76,19 +76,6 @@ public:
|
||||
const Block & sample_block_,
|
||||
const UInt64 max_block_size_)
|
||||
: PostgreSQLSource<T>(tx_, query_str_, sample_block_, max_block_size_, false) {}
|
||||
|
||||
Chunk generate() override
|
||||
{
|
||||
if (!is_initialized)
|
||||
{
|
||||
Base::stream = std::make_unique<pqxx::stream_from>(*Base::tx, pqxx::from_query, std::string_view(Base::query_str));
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
return Base::generate();
|
||||
}
|
||||
|
||||
bool is_initialized = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ SRCS(
|
||||
TTLUpdateInfoAlgorithm.cpp
|
||||
copyData.cpp
|
||||
finalizeBlock.cpp
|
||||
formatBlock.cpp
|
||||
materializeBlock.cpp
|
||||
narrowBlockInputStreams.cpp
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <Interpreters/executeQuery.h>
|
||||
#include <Parsers/queryToString.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <Common/ZooKeeper/KeeperException.h>
|
||||
#include <Common/ZooKeeper/Types.h>
|
||||
#include <Common/ZooKeeper/ZooKeeper.h>
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <Common/ProfileEvents.h>
|
||||
#include <Common/ProfilingScopedRWLock.h>
|
||||
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
#include <Dictionaries//DictionarySource.h>
|
||||
#include <Dictionaries/HierarchyDictionariesUtils.h>
|
||||
|
||||
#include <Processors/Executors/PullingPipelineExecutor.h>
|
||||
@ -18,21 +18,21 @@
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event DictCacheKeysRequested;
|
||||
extern const Event DictCacheKeysRequestedMiss;
|
||||
extern const Event DictCacheKeysRequestedFound;
|
||||
extern const Event DictCacheKeysExpired;
|
||||
extern const Event DictCacheKeysNotFound;
|
||||
extern const Event DictCacheKeysHit;
|
||||
extern const Event DictCacheRequestTimeNs;
|
||||
extern const Event DictCacheRequests;
|
||||
extern const Event DictCacheLockWriteNs;
|
||||
extern const Event DictCacheLockReadNs;
|
||||
extern const Event DictCacheKeysRequested;
|
||||
extern const Event DictCacheKeysRequestedMiss;
|
||||
extern const Event DictCacheKeysRequestedFound;
|
||||
extern const Event DictCacheKeysExpired;
|
||||
extern const Event DictCacheKeysNotFound;
|
||||
extern const Event DictCacheKeysHit;
|
||||
extern const Event DictCacheRequestTimeNs;
|
||||
extern const Event DictCacheRequests;
|
||||
extern const Event DictCacheLockWriteNs;
|
||||
extern const Event DictCacheLockReadNs;
|
||||
}
|
||||
|
||||
namespace CurrentMetrics
|
||||
{
|
||||
extern const Metric DictCacheRequests;
|
||||
extern const Metric DictCacheRequests;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
|
@ -648,6 +648,16 @@ static const PaddedPODArray<T> & getColumnVectorData(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static ColumnPtr getColumnFromPODArray(const PaddedPODArray<T> & array)
|
||||
{
|
||||
auto column_vector = ColumnVector<T>::create();
|
||||
column_vector->getData().reserve(array.size());
|
||||
column_vector->getData().insert(array.begin(), array.end());
|
||||
|
||||
return column_vector;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "DictionaryBlockInputStream.h"
|
||||
#include "DictionarySource.h"
|
||||
#include <Dictionaries/DictionaryHelpers.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -12,7 +13,7 @@ DictionarySourceData::DictionarySourceData(
|
||||
std::shared_ptr<const IDictionary> dictionary_, PaddedPODArray<UInt64> && ids_, const Names & column_names_)
|
||||
: num_rows(ids_.size())
|
||||
, dictionary(dictionary_)
|
||||
, column_names(column_names_)
|
||||
, column_names(column_names_.begin(), column_names_.end())
|
||||
, ids(std::move(ids_))
|
||||
, key_type(DictionaryInputStreamKeyType::Id)
|
||||
{
|
||||
@ -24,7 +25,7 @@ DictionarySourceData::DictionarySourceData(
|
||||
const Names & column_names_)
|
||||
: num_rows(keys.size())
|
||||
, dictionary(dictionary_)
|
||||
, column_names(column_names_)
|
||||
, column_names(column_names_.begin(), column_names_.end())
|
||||
, key_type(DictionaryInputStreamKeyType::ComplexKey)
|
||||
{
|
||||
const DictionaryStructure & dictionary_structure = dictionary->getStructure();
|
||||
@ -39,7 +40,7 @@ DictionarySourceData::DictionarySourceData(
|
||||
GetColumnsFunction && get_view_columns_function_)
|
||||
: num_rows(data_columns_.front()->size())
|
||||
, dictionary(dictionary_)
|
||||
, column_names(column_names_)
|
||||
, column_names(column_names_.begin(), column_names_.end())
|
||||
, data_columns(data_columns_)
|
||||
, get_key_columns_function(std::move(get_key_columns_function_))
|
||||
, get_view_columns_function(std::move(get_view_columns_function_))
|
||||
@ -102,8 +103,6 @@ Block DictionarySourceData::fillBlock(
|
||||
const DataTypes & types,
|
||||
ColumnsWithTypeAndName && view) const
|
||||
{
|
||||
std::unordered_set<std::string> names(column_names.begin(), column_names.end());
|
||||
|
||||
DataTypes data_types = types;
|
||||
ColumnsWithTypeAndName block_columns;
|
||||
|
||||
@ -114,13 +113,13 @@ Block DictionarySourceData::fillBlock(
|
||||
data_types.push_back(key.type);
|
||||
|
||||
for (const auto & column : view)
|
||||
if (names.find(column.name) != names.end())
|
||||
if (column_names.find(column.name) != column_names.end())
|
||||
block_columns.push_back(column);
|
||||
|
||||
const DictionaryStructure & structure = dictionary->getStructure();
|
||||
ColumnPtr ids_column = getColumnFromIds(ids_to_fill);
|
||||
ColumnPtr ids_column = getColumnFromPODArray(ids_to_fill);
|
||||
|
||||
if (structure.id && names.find(structure.id->name) != names.end())
|
||||
if (structure.id && column_names.find(structure.id->name) != column_names.end())
|
||||
{
|
||||
block_columns.emplace_back(ids_column, std::make_shared<DataTypeUInt64>(), structure.id->name);
|
||||
}
|
||||
@ -129,7 +128,7 @@ Block DictionarySourceData::fillBlock(
|
||||
|
||||
for (const auto & attribute : structure.attributes)
|
||||
{
|
||||
if (names.find(attribute.name) != names.end())
|
||||
if (column_names.find(attribute.name) != column_names.end())
|
||||
{
|
||||
ColumnPtr column;
|
||||
|
||||
@ -159,13 +158,6 @@ Block DictionarySourceData::fillBlock(
|
||||
return Block(block_columns);
|
||||
}
|
||||
|
||||
ColumnPtr DictionarySourceData::getColumnFromIds(const PaddedPODArray<UInt64> & ids_to_fill)
|
||||
{
|
||||
auto column_vector = ColumnVector<UInt64>::create();
|
||||
column_vector->getData().assign(ids_to_fill);
|
||||
return column_vector;
|
||||
}
|
||||
|
||||
void DictionarySourceData::fillKeyColumns(
|
||||
const PaddedPODArray<StringRef> & keys,
|
||||
size_t start,
|
@ -7,19 +7,14 @@
|
||||
#include <Columns/IColumn.h>
|
||||
#include <Core/Names.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <common/logger_useful.h>
|
||||
#include "DictionaryBlockInputStreamBase.h"
|
||||
#include "DictionaryStructure.h"
|
||||
#include "IDictionary.h"
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <Dictionaries/IDictionary.h>
|
||||
#include <Dictionaries/DictionarySourceBase.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/// TODO: Remove this class
|
||||
/* BlockInputStream implementation for external dictionaries
|
||||
* read() returns blocks consisting of the in-memory contents of the dictionaries
|
||||
*/
|
||||
class DictionarySourceData
|
||||
{
|
||||
public:
|
||||
@ -56,8 +51,6 @@ private:
|
||||
const DataTypes & types,
|
||||
ColumnsWithTypeAndName && view) const;
|
||||
|
||||
static ColumnPtr getColumnFromIds(const PaddedPODArray<UInt64> & ids_to_fill);
|
||||
|
||||
static void fillKeyColumns(
|
||||
const PaddedPODArray<StringRef> & keys,
|
||||
size_t start,
|
||||
@ -67,7 +60,7 @@ private:
|
||||
|
||||
const size_t num_rows;
|
||||
std::shared_ptr<const IDictionary> dictionary;
|
||||
Names column_names;
|
||||
std::unordered_set<std::string> column_names;
|
||||
PaddedPODArray<UInt64> ids;
|
||||
ColumnsWithTypeAndName key_columns;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "DictionaryBlockInputStreamBase.h"
|
||||
#include "DictionarySourceBase.h"
|
||||
|
||||
namespace DB
|
||||
{
|
@ -13,7 +13,7 @@
|
||||
#include <Processors/QueryPipeline.h>
|
||||
#include <Processors/Executors/PullingPipelineExecutor.h>
|
||||
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
#include <Dictionaries//DictionarySource.h>
|
||||
#include <Dictionaries/DictionaryFactory.h>
|
||||
#include <Dictionaries/HierarchyDictionariesUtils.h>
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
#include <Dictionaries//DictionarySource.h>
|
||||
#include <Dictionaries/DictionaryFactory.h>
|
||||
#include <Dictionaries/HierarchyDictionariesUtils.h>
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <common/itoa.h>
|
||||
#include <common/map.h>
|
||||
#include <common/range.h>
|
||||
#include <Dictionaries/DictionaryBlockInputStream.h>
|
||||
#include <Dictionaries/DictionarySource.h>
|
||||
#include <Dictionaries/DictionaryFactory.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
#include <numeric>
|
||||
#include <cmath>
|
||||
|
||||
#include "DictionaryBlockInputStream.h"
|
||||
#include "DictionaryFactory.h"
|
||||
|
||||
#include <Columns/ColumnArray.h>
|
||||
#include <Columns/ColumnTuple.h>
|
||||
#include <DataTypes/DataTypeArray.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
#include <Dictionaries/DictionaryFactory.h>
|
||||
#include <Dictionaries/DictionarySource.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
#include <DataTypes/DataTypeDate.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnVector.h>
|
||||
#include <Columns/IColumn.h>
|
||||
#include <DataTypes/DataTypeDate.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <common/range.h>
|
||||
#include "DictionaryBlockInputStreamBase.h"
|
||||
#include "DictionaryStructure.h"
|
||||
#include "IDictionary.h"
|
||||
#include "RangeHashedDictionary.h"
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <Dictionaries/IDictionary.h>
|
||||
#include <Dictionaries/DictionarySourceBase.h>
|
||||
#include <Dictionaries/DictionaryHelpers.h>
|
||||
#include <Dictionaries/RangeHashedDictionary.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -31,8 +31,6 @@ public:
|
||||
size_t getNumRows() const { return ids.size(); }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
ColumnPtr getColumnFromPODArray(const PaddedPODArray<T> & array) const;
|
||||
|
||||
Block fillBlock(
|
||||
const PaddedPODArray<Key> & ids_to_fill,
|
||||
@ -86,17 +84,6 @@ Block RangeDictionarySourceData<RangeType>::getBlock(size_t start, size_t length
|
||||
return fillBlock(block_ids, block_start_dates, block_end_dates);
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
template <typename T>
|
||||
ColumnPtr RangeDictionarySourceData<RangeType>::getColumnFromPODArray(const PaddedPODArray<T> & array) const
|
||||
{
|
||||
auto column_vector = ColumnVector<T>::create();
|
||||
column_vector->getData().reserve(array.size());
|
||||
column_vector->getData().insert(array.begin(), array.end());
|
||||
|
||||
return column_vector;
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
PaddedPODArray<Int64> RangeDictionarySourceData<RangeType>::makeDateKey(
|
||||
const PaddedPODArray<RangeType> & block_start_dates, const PaddedPODArray<RangeType> & block_end_dates) const
|
@ -2,11 +2,11 @@
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <Common/TypeList.h>
|
||||
#include <common/range.h>
|
||||
#include "DictionaryFactory.h"
|
||||
#include "RangeDictionaryBlockInputStream.h"
|
||||
#include <Interpreters/castColumn.h>
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
#include <Dictionaries/DictionaryFactory.h>
|
||||
#include <Dictionaries/RangeDictionarySource.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -9,10 +9,10 @@
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Common/HashTable/HashMap.h>
|
||||
#include <Common/HashTable/HashSet.h>
|
||||
#include "DictionaryStructure.h"
|
||||
#include "IDictionary.h"
|
||||
#include "IDictionarySource.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include <Dictionaries/DictionaryStructure.h>
|
||||
#include <Dictionaries/IDictionary.h>
|
||||
#include <Dictionaries/IDictionarySource.h>
|
||||
#include <Dictionaries/DictionaryHelpers.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
|
||||
#include <common/unaligned.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <Common/randomSeed.h>
|
||||
#include <Common/Arena.h>
|
||||
#include <Common/ArenaWithFreeLists.h>
|
||||
|
@ -212,13 +212,11 @@ BlockOutputStreamPtr FormatFactory::getOutputStreamParallelIfPossible(
|
||||
|
||||
const Settings & settings = context->getSettingsRef();
|
||||
bool parallel_formatting = settings.output_format_parallel_formatting;
|
||||
auto format_settings = _format_settings ? *_format_settings : getFormatSettings(context);
|
||||
|
||||
if (output_getter && parallel_formatting && getCreators(name).supports_parallel_formatting
|
||||
&& !settings.output_format_json_array_of_rows)
|
||||
if (output_getter && parallel_formatting && getCreators(name).supports_parallel_formatting && !settings.output_format_json_array_of_rows
|
||||
&& !format_settings.mysql_wire.sequence_id)
|
||||
{
|
||||
auto format_settings = _format_settings
|
||||
? *_format_settings : getFormatSettings(context);
|
||||
|
||||
auto formatter_creator = [output_getter, sample, callback, format_settings]
|
||||
(WriteBuffer & output) -> OutputFormatPtr
|
||||
{ return output_getter(output, sample, {std::move(callback)}, format_settings);};
|
||||
@ -317,7 +315,7 @@ OutputFormatPtr FormatFactory::getOutputFormatParallelIfPossible(
|
||||
const Settings & settings = context->getSettingsRef();
|
||||
|
||||
if (settings.output_format_parallel_formatting && getCreators(name).supports_parallel_formatting
|
||||
&& !settings.output_format_json_array_of_rows)
|
||||
&& !settings.output_format_json_array_of_rows && !format_settings.mysql_wire.sequence_id)
|
||||
{
|
||||
auto formatter_creator = [output_getter, sample, callback, format_settings]
|
||||
(WriteBuffer & output) -> OutputFormatPtr
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include <common/types.h>
|
||||
|
||||
#include <Core/Defines.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -977,13 +977,14 @@ bool Aggregator::executeOnBlock(Columns columns, UInt64 num_rows, AggregatedData
|
||||
/// For the case when there are no keys (all aggregate into one row).
|
||||
if (result.type == AggregatedDataVariants::Type::without_key)
|
||||
{
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
if (compiled_aggregate_functions_holder)
|
||||
{
|
||||
executeWithoutKeyImpl<true>(result.without_key, num_rows, aggregate_functions_instructions.data(), result.aggregates_pool);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/// TODO: Enable compilation after investigation
|
||||
// #if USE_EMBEDDED_COMPILER
|
||||
// if (compiled_aggregate_functions_holder)
|
||||
// {
|
||||
// executeWithoutKeyImpl<true>(result.without_key, num_rows, aggregate_functions_instructions.data(), result.aggregates_pool);
|
||||
// }
|
||||
// else
|
||||
// #endif
|
||||
{
|
||||
executeWithoutKeyImpl<false>(result.without_key, num_rows, aggregate_functions_instructions.data(), result.aggregates_pool);
|
||||
}
|
||||
|
@ -1091,7 +1091,14 @@ void AsynchronousMetrics::update(std::chrono::system_clock::time_point update_ti
|
||||
{
|
||||
sensor_file->rewind();
|
||||
Int64 temperature = 0;
|
||||
readText(temperature, *sensor_file);
|
||||
try
|
||||
{
|
||||
readText(temperature, *sensor_file);
|
||||
}
|
||||
catch (const ErrnoException & e)
|
||||
{
|
||||
LOG_DEBUG(&Poco::Logger::get("AsynchronousMetrics"), "Hardware monitor '{}', sensor '{}' exists but could not be read, error {}.", hwmon_name, sensor_name, e.getErrno());
|
||||
}
|
||||
|
||||
if (sensor_name.empty())
|
||||
new_values[fmt::format("Temperature_{}", hwmon_name)] = temperature * 0.001;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <DataTypes/DataTypeDateTime.h>
|
||||
#include <Common/ClickHouseRevision.h>
|
||||
#include <Common/SymbolIndex.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
|
||||
#if !defined(ARCADIA_BUILD)
|
||||
# include <Common/config_version.h>
|
||||
|
@ -158,15 +158,20 @@ DDLWorker::DDLWorker(
|
||||
const Poco::Util::AbstractConfiguration * config,
|
||||
const String & prefix,
|
||||
const String & logger_name,
|
||||
const CurrentMetrics::Metric * max_entry_metric_)
|
||||
const CurrentMetrics::Metric * max_entry_metric_,
|
||||
const CurrentMetrics::Metric * max_pushed_entry_metric_)
|
||||
: context(Context::createCopy(context_))
|
||||
, log(&Poco::Logger::get(logger_name))
|
||||
, pool_size(pool_size_)
|
||||
, max_entry_metric(max_entry_metric_)
|
||||
, max_pushed_entry_metric(max_pushed_entry_metric_)
|
||||
{
|
||||
if (max_entry_metric)
|
||||
CurrentMetrics::set(*max_entry_metric, 0);
|
||||
|
||||
if (max_pushed_entry_metric)
|
||||
CurrentMetrics::set(*max_pushed_entry_metric, 0);
|
||||
|
||||
if (1 < pool_size)
|
||||
{
|
||||
LOG_WARNING(log, "DDLWorker is configured to use multiple threads. "
|
||||
@ -1046,6 +1051,15 @@ String DDLWorker::enqueueQuery(DDLLogEntry & entry)
|
||||
zookeeper->createAncestors(query_path_prefix);
|
||||
|
||||
String node_path = zookeeper->create(query_path_prefix, entry.toString(), zkutil::CreateMode::PersistentSequential);
|
||||
if (max_pushed_entry_metric)
|
||||
{
|
||||
String str_buf = node_path.substr(query_path_prefix.length());
|
||||
DB::ReadBufferFromString in(str_buf);
|
||||
CurrentMetrics::Metric id;
|
||||
readText(id, in);
|
||||
id = std::max(*max_pushed_entry_metric, id);
|
||||
CurrentMetrics::set(*max_pushed_entry_metric, id);
|
||||
}
|
||||
|
||||
/// We cannot create status dirs in a single transaction with previous request,
|
||||
/// because we don't know node_path until previous request is executed.
|
||||
|
@ -44,7 +44,7 @@ class DDLWorker
|
||||
{
|
||||
public:
|
||||
DDLWorker(int pool_size_, const std::string & zk_root_dir, ContextPtr context_, const Poco::Util::AbstractConfiguration * config, const String & prefix,
|
||||
const String & logger_name = "DDLWorker", const CurrentMetrics::Metric * max_entry_metric_ = nullptr);
|
||||
const String & logger_name = "DDLWorker", const CurrentMetrics::Metric * max_entry_metric_ = nullptr, const CurrentMetrics::Metric * max_pushed_entry_metric_ = nullptr);
|
||||
virtual ~DDLWorker();
|
||||
|
||||
/// Pushes query into DDL queue, returns path to created node
|
||||
@ -148,6 +148,7 @@ protected:
|
||||
|
||||
std::atomic<UInt64> max_id = 0;
|
||||
const CurrentMetrics::Metric * max_entry_metric;
|
||||
const CurrentMetrics::Metric * max_pushed_entry_metric;
|
||||
};
|
||||
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <Core/BackgroundSchedulePool.h>
|
||||
#include <Interpreters/Context_fwd.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -764,7 +764,7 @@ void InterpreterCreateQuery::assertOrSetUUID(ASTCreateQuery & create, const Data
|
||||
const auto * kind = create.is_dictionary ? "Dictionary" : "Table";
|
||||
const auto * kind_upper = create.is_dictionary ? "DICTIONARY" : "TABLE";
|
||||
|
||||
if (database->getEngineName() == "Replicated" && getContext()->getClientInfo().query_kind == ClientInfo::QueryKind::SECONDARY_QUERY
|
||||
if (database->getEngineName() == "Replicated" && getContext()->getClientInfo().is_replicated_database_internal
|
||||
&& !internal)
|
||||
{
|
||||
if (create.uuid == UUIDHelpers::Nil)
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <Common/CurrentMetrics.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
|
||||
|
||||
namespace CurrentMetrics
|
||||
{
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <common/types.h>
|
||||
#include <Core/Defines.h>
|
||||
#include <Storages/IStorage.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
#include <Parsers/ParserCreateQuery.h>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <Columns/ColumnLowCardinality.h>
|
||||
#include <Columns/ColumnNullable.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
|
||||
#include <DataStreams/materializeBlock.h>
|
||||
|
||||
@ -105,25 +106,57 @@ DataTypePtr convertTypeToNullable(const DataTypePtr & type)
|
||||
return type;
|
||||
}
|
||||
|
||||
/// Convert column to nullable. If column LowCardinality or Const, convert nested column.
|
||||
/// Returns nullptr if conversion cannot be performed.
|
||||
static ColumnPtr tryConvertColumnToNullable(const ColumnPtr & col)
|
||||
{
|
||||
if (isColumnNullable(*col) || col->canBeInsideNullable())
|
||||
return makeNullable(col);
|
||||
|
||||
if (col->lowCardinality())
|
||||
{
|
||||
auto mut_col = IColumn::mutate(std::move(col));
|
||||
ColumnLowCardinality * col_lc = assert_cast<ColumnLowCardinality *>(mut_col.get());
|
||||
if (col_lc->nestedIsNullable())
|
||||
{
|
||||
return mut_col;
|
||||
}
|
||||
else if (col_lc->nestedCanBeInsideNullable())
|
||||
{
|
||||
col_lc->nestedToNullable();
|
||||
return mut_col;
|
||||
}
|
||||
}
|
||||
else if (const ColumnConst * col_const = checkAndGetColumn<ColumnConst>(*col))
|
||||
{
|
||||
const auto & nested = col_const->getDataColumnPtr();
|
||||
if (nested->isNullable() || nested->canBeInsideNullable())
|
||||
{
|
||||
return makeNullable(col);
|
||||
}
|
||||
else if (nested->lowCardinality())
|
||||
{
|
||||
ColumnPtr nested_nullable = tryConvertColumnToNullable(nested);
|
||||
if (nested_nullable)
|
||||
return ColumnConst::create(nested_nullable, col_const->size());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void convertColumnToNullable(ColumnWithTypeAndName & column)
|
||||
{
|
||||
column.type = convertTypeToNullable(column.type);
|
||||
|
||||
if (!column.column)
|
||||
{
|
||||
column.type = convertTypeToNullable(column.type);
|
||||
return;
|
||||
|
||||
if (column.column->lowCardinality())
|
||||
{
|
||||
/// Convert nested to nullable, not LowCardinality itself
|
||||
auto mut_col = IColumn::mutate(std::move(column.column));
|
||||
ColumnLowCardinality * col_as_lc = assert_cast<ColumnLowCardinality *>(mut_col.get());
|
||||
if (!col_as_lc->nestedIsNullable())
|
||||
col_as_lc->nestedToNullable();
|
||||
column.column = std::move(mut_col);
|
||||
}
|
||||
else if (column.column->canBeInsideNullable())
|
||||
|
||||
ColumnPtr nullable_column = tryConvertColumnToNullable(column.column);
|
||||
if (nullable_column)
|
||||
{
|
||||
column.column = makeNullable(column.column);
|
||||
column.type = convertTypeToNullable(column.type);
|
||||
column.column = std::move(nullable_column);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ SRCS(
|
||||
ASTCreateRowPolicyQuery.cpp
|
||||
ASTCreateSettingsProfileQuery.cpp
|
||||
ASTCreateUserQuery.cpp
|
||||
ASTDatabaseOrNone.cpp
|
||||
ASTDictionary.cpp
|
||||
ASTDictionaryAttributeDeclaration.cpp
|
||||
ASTDropAccessEntityQuery.cpp
|
||||
@ -95,6 +96,7 @@ SRCS(
|
||||
ParserCreateSettingsProfileQuery.cpp
|
||||
ParserCreateUserQuery.cpp
|
||||
ParserDataType.cpp
|
||||
ParserDatabaseOrNone.cpp
|
||||
ParserDescribeTableQuery.cpp
|
||||
ParserDictionary.cpp
|
||||
ParserDictionaryAttributeDeclaration.cpp
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <Processors/Formats/IInputFormat.h>
|
||||
#include <DataStreams/SizeLimits.h>
|
||||
#include <Poco/Timespan.h>
|
||||
#include <Common/Stopwatch.h>
|
||||
|
||||
class Stopwatch;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -1166,6 +1166,23 @@ void WindowTransform::appendChunk(Chunk & chunk)
|
||||
// Write out the aggregation results.
|
||||
writeOutCurrentRow();
|
||||
|
||||
if (isCancelled())
|
||||
{
|
||||
// Good time to check if the query is cancelled. Checking once
|
||||
// per block might not be enough in severe quadratic cases.
|
||||
// Just leave the work halfway through and return, the 'prepare'
|
||||
// method will figure out what to do. Note that this doesn't
|
||||
// handle 'max_execution_time' and other limits, because these
|
||||
// limits are only updated between blocks. Eventually we should
|
||||
// start updating them in background and canceling the processor,
|
||||
// like we do for Ctrl+C handling.
|
||||
//
|
||||
// This class is final, so the check should hopefully be
|
||||
// devirtualized and become a single never-taken branch that is
|
||||
// basically free.
|
||||
return;
|
||||
}
|
||||
|
||||
// Move to the next row. The frame will have to be recalculated.
|
||||
// The peer group start is updated at the beginning of the loop,
|
||||
// because current_row might now be past-the-end.
|
||||
@ -1255,10 +1272,12 @@ IProcessor::Status WindowTransform::prepare()
|
||||
// next_output_block_number, first_not_ready_row, first_block_number,
|
||||
// blocks.size());
|
||||
|
||||
if (output.isFinished())
|
||||
if (output.isFinished() || isCancelled())
|
||||
{
|
||||
// The consumer asked us not to continue (or we decided it ourselves),
|
||||
// so we abort.
|
||||
// so we abort. Not sure what the difference between the two conditions
|
||||
// is, but it seemed that output.isFinished() is not enough to cancel on
|
||||
// Ctrl+C. Test manually if you change it.
|
||||
input.close();
|
||||
return Status::Finished;
|
||||
}
|
||||
|
@ -80,8 +80,10 @@ struct RowNumber
|
||||
* the order of input data. This property also trivially holds for the ROWS and
|
||||
* GROUPS frames. For the RANGE frame, the proof requires the additional fact
|
||||
* that the ranges are specified in terms of (the single) ORDER BY column.
|
||||
*
|
||||
* `final` is so that the isCancelled() is devirtualized, we call it every row.
|
||||
*/
|
||||
class WindowTransform : public IProcessor /* public ISimpleTransform */
|
||||
class WindowTransform final : public IProcessor
|
||||
{
|
||||
public:
|
||||
WindowTransform(
|
||||
|
@ -7,14 +7,8 @@ PEERDIR(
|
||||
clickhouse/src/Common
|
||||
contrib/libs/msgpack
|
||||
contrib/libs/protobuf
|
||||
contrib/libs/arrow
|
||||
)
|
||||
|
||||
ADDINCL(
|
||||
contrib/libs/arrow/src
|
||||
)
|
||||
|
||||
CFLAGS(-DUSE_ARROW=1)
|
||||
|
||||
SRCS(
|
||||
Chunk.cpp
|
||||
@ -31,11 +25,6 @@ SRCS(
|
||||
Formats/IOutputFormat.cpp
|
||||
Formats/IRowInputFormat.cpp
|
||||
Formats/IRowOutputFormat.cpp
|
||||
Formats/Impl/ArrowBlockInputFormat.cpp
|
||||
Formats/Impl/ArrowBlockOutputFormat.cpp
|
||||
Formats/Impl/ArrowBufferedStreams.cpp
|
||||
Formats/Impl/ArrowColumnToCHColumn.cpp
|
||||
Formats/Impl/CHColumnToArrowColumn.cpp
|
||||
Formats/Impl/BinaryRowInputFormat.cpp
|
||||
Formats/Impl/BinaryRowOutputFormat.cpp
|
||||
Formats/Impl/CSVRowInputFormat.cpp
|
||||
|
@ -146,6 +146,9 @@ try
|
||||
catch (...) /// Exception while we looking for a task, reschedule
|
||||
{
|
||||
tryLogCurrentException(__PRETTY_FUNCTION__);
|
||||
|
||||
/// Why do we scheduleTask again?
|
||||
/// To retry on exception, since it may be some temporary exception.
|
||||
scheduleTask(/* with_backoff = */ true);
|
||||
}
|
||||
|
||||
@ -180,10 +183,16 @@ void IBackgroundJobExecutor::triggerTask()
|
||||
}
|
||||
|
||||
void IBackgroundJobExecutor::backgroundTaskFunction()
|
||||
try
|
||||
{
|
||||
if (!scheduleJob())
|
||||
scheduleTask(/* with_backoff = */ true);
|
||||
}
|
||||
catch (...) /// Catch any exception to avoid thread termination.
|
||||
{
|
||||
tryLogCurrentException(__PRETTY_FUNCTION__);
|
||||
scheduleTask(/* with_backoff = */ true);
|
||||
}
|
||||
|
||||
IBackgroundJobExecutor::~IBackgroundJobExecutor()
|
||||
{
|
||||
|
@ -1663,7 +1663,12 @@ NameToNameVector MergeTreeDataMergerMutator::collectFilesForRenames(
|
||||
{
|
||||
if (command.type == MutationCommand::Type::DROP_INDEX)
|
||||
{
|
||||
if (source_part->checksums.has(INDEX_FILE_PREFIX + command.column_name + ".idx"))
|
||||
if (source_part->checksums.has(INDEX_FILE_PREFIX + command.column_name + ".idx2"))
|
||||
{
|
||||
rename_vector.emplace_back(INDEX_FILE_PREFIX + command.column_name + ".idx2", "");
|
||||
rename_vector.emplace_back(INDEX_FILE_PREFIX + command.column_name + mrk_extension, "");
|
||||
}
|
||||
else if (source_part->checksums.has(INDEX_FILE_PREFIX + command.column_name + ".idx"))
|
||||
{
|
||||
rename_vector.emplace_back(INDEX_FILE_PREFIX + command.column_name + ".idx", "");
|
||||
rename_vector.emplace_back(INDEX_FILE_PREFIX + command.column_name + mrk_extension, "");
|
||||
@ -1749,6 +1754,7 @@ NameSet MergeTreeDataMergerMutator::collectFilesToSkip(
|
||||
for (const auto & index : indices_to_recalc)
|
||||
{
|
||||
files_to_skip.insert(index->getFileName() + ".idx");
|
||||
files_to_skip.insert(index->getFileName() + ".idx2");
|
||||
files_to_skip.insert(index->getFileName() + mrk_extension);
|
||||
}
|
||||
for (const auto & projection : projections_to_recalc)
|
||||
@ -1893,8 +1899,11 @@ std::set<MergeTreeIndexPtr> MergeTreeDataMergerMutator::getIndicesToRecalculate(
|
||||
{
|
||||
const auto & index = indices[i];
|
||||
|
||||
bool has_index =
|
||||
source_part->checksums.has(INDEX_FILE_PREFIX + index.name + ".idx") ||
|
||||
source_part->checksums.has(INDEX_FILE_PREFIX + index.name + ".idx2");
|
||||
// If we ask to materialize and it already exists
|
||||
if (!source_part->checksums.has(INDEX_FILE_PREFIX + index.name + ".idx") && materialized_indices.count(index.name))
|
||||
if (!has_index && materialized_indices.count(index.name))
|
||||
{
|
||||
if (indices_to_recalc.insert(index_factory.get(index)).second)
|
||||
{
|
||||
|
@ -9,11 +9,6 @@ namespace ErrorCodes
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr auto INDEX_FILE_EXTENSION = ".idx";
|
||||
}
|
||||
|
||||
void MergeTreeDataPartWriterOnDisk::Stream::finalize()
|
||||
{
|
||||
compressed.next();
|
||||
@ -165,7 +160,7 @@ void MergeTreeDataPartWriterOnDisk::initSkipIndices()
|
||||
std::make_unique<MergeTreeDataPartWriterOnDisk::Stream>(
|
||||
stream_name,
|
||||
data_part->volume->getDisk(),
|
||||
part_path + stream_name, INDEX_FILE_EXTENSION,
|
||||
part_path + stream_name, index_helper->getSerializedFileExtension(),
|
||||
part_path + stream_name, marks_file_extension,
|
||||
default_codec, settings.max_compress_block_size));
|
||||
skip_indices_aggregators.push_back(index_helper->createIndexAggregator());
|
||||
|
@ -1457,9 +1457,10 @@ MarkRanges MergeTreeDataSelectExecutor::filterMarksUsingIndex(
|
||||
size_t & granules_dropped,
|
||||
Poco::Logger * log)
|
||||
{
|
||||
if (!part->volume->getDisk()->exists(part->getFullRelativePath() + index_helper->getFileName() + ".idx"))
|
||||
const std::string & path_prefix = part->getFullRelativePath() + index_helper->getFileName();
|
||||
if (!index_helper->getDeserializedFormat(part->volume->getDisk(), path_prefix))
|
||||
{
|
||||
LOG_DEBUG(log, "File for index {} does not exist. Skipping it.", backQuote(index_helper->index.name));
|
||||
LOG_DEBUG(log, "File for index {} does not exist ({}.*). Skipping it.", backQuote(index_helper->index.name), path_prefix);
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
@ -101,14 +101,17 @@ MergeTreeIndexGranuleFullText::MergeTreeIndexGranuleFullText(
|
||||
void MergeTreeIndexGranuleFullText::serializeBinary(WriteBuffer & ostr) const
|
||||
{
|
||||
if (empty())
|
||||
throw Exception("Attempt to write empty fulltext index " + backQuote(index_name), ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Attempt to write empty fulltext index {}.", backQuote(index_name));
|
||||
|
||||
for (const auto & bloom_filter : bloom_filters)
|
||||
ostr.write(reinterpret_cast<const char *>(bloom_filter.getFilter().data()), params.filter_size);
|
||||
}
|
||||
|
||||
void MergeTreeIndexGranuleFullText::deserializeBinary(ReadBuffer & istr)
|
||||
void MergeTreeIndexGranuleFullText::deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version)
|
||||
{
|
||||
if (version != 1)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown index version {}.", version);
|
||||
|
||||
for (auto & bloom_filter : bloom_filters)
|
||||
{
|
||||
istr.read(reinterpret_cast<char *>(
|
||||
|
@ -45,7 +45,7 @@ struct MergeTreeIndexGranuleFullText final : public IMergeTreeIndexGranule
|
||||
~MergeTreeIndexGranuleFullText() override = default;
|
||||
|
||||
void serializeBinary(WriteBuffer & ostr) const override;
|
||||
void deserializeBinary(ReadBuffer & istr) override;
|
||||
void deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version) override;
|
||||
|
||||
bool empty() const override { return !has_elems; }
|
||||
|
||||
|
@ -84,10 +84,12 @@ bool MergeTreeIndexGranuleBloomFilter::empty() const
|
||||
return !total_rows;
|
||||
}
|
||||
|
||||
void MergeTreeIndexGranuleBloomFilter::deserializeBinary(ReadBuffer & istr)
|
||||
void MergeTreeIndexGranuleBloomFilter::deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version)
|
||||
{
|
||||
if (!empty())
|
||||
throw Exception("Cannot read data to a non-empty bloom filter index.", ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot read data to a non-empty bloom filter index.");
|
||||
if (version != 1)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown index version {}.", version);
|
||||
|
||||
readVarUInt(total_rows, istr);
|
||||
for (auto & filter : bloom_filters)
|
||||
@ -102,7 +104,7 @@ void MergeTreeIndexGranuleBloomFilter::deserializeBinary(ReadBuffer & istr)
|
||||
void MergeTreeIndexGranuleBloomFilter::serializeBinary(WriteBuffer & ostr) const
|
||||
{
|
||||
if (empty())
|
||||
throw Exception("Attempt to write empty bloom filter index.", ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Attempt to write empty bloom filter index.");
|
||||
|
||||
static size_t atom_size = 8;
|
||||
writeVarUInt(total_rows, ostr);
|
||||
|
@ -16,8 +16,7 @@ public:
|
||||
bool empty() const override;
|
||||
|
||||
void serializeBinary(WriteBuffer & ostr) const override;
|
||||
|
||||
void deserializeBinary(ReadBuffer & istr) override;
|
||||
void deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version) override;
|
||||
|
||||
const std::vector<BloomFilterPtr> & getFilters() const { return bloom_filters; }
|
||||
|
||||
|
@ -40,28 +40,12 @@ void MergeTreeIndexGranuleMinMax::serializeBinary(WriteBuffer & ostr) const
|
||||
const DataTypePtr & type = index_sample_block.getByPosition(i).type;
|
||||
auto serialization = type->getDefaultSerialization();
|
||||
|
||||
if (!type->isNullable())
|
||||
{
|
||||
serialization->serializeBinary(hyperrectangle[i].left, ostr);
|
||||
serialization->serializeBinary(hyperrectangle[i].right, ostr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// NOTE: that this serialization differs from
|
||||
/// IMergeTreeDataPart::MinMaxIndex::store() due to preserve
|
||||
/// backward compatibility.
|
||||
bool is_null = hyperrectangle[i].left.isNull() || hyperrectangle[i].right.isNull(); // one is enough
|
||||
writeBinary(is_null, ostr);
|
||||
if (!is_null)
|
||||
{
|
||||
serialization->serializeBinary(hyperrectangle[i].left, ostr);
|
||||
serialization->serializeBinary(hyperrectangle[i].right, ostr);
|
||||
}
|
||||
}
|
||||
serialization->serializeBinary(hyperrectangle[i].left, ostr);
|
||||
serialization->serializeBinary(hyperrectangle[i].right, ostr);
|
||||
}
|
||||
}
|
||||
|
||||
void MergeTreeIndexGranuleMinMax::deserializeBinary(ReadBuffer & istr)
|
||||
void MergeTreeIndexGranuleMinMax::deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version)
|
||||
{
|
||||
hyperrectangle.clear();
|
||||
Field min_val;
|
||||
@ -72,29 +56,53 @@ void MergeTreeIndexGranuleMinMax::deserializeBinary(ReadBuffer & istr)
|
||||
const DataTypePtr & type = index_sample_block.getByPosition(i).type;
|
||||
auto serialization = type->getDefaultSerialization();
|
||||
|
||||
if (!type->isNullable())
|
||||
switch (version)
|
||||
{
|
||||
serialization->deserializeBinary(min_val, istr);
|
||||
serialization->deserializeBinary(max_val, istr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// NOTE: that this serialization differs from
|
||||
/// IMergeTreeDataPart::MinMaxIndex::load() due to preserve
|
||||
/// backward compatibility.
|
||||
bool is_null;
|
||||
readBinary(is_null, istr);
|
||||
if (!is_null)
|
||||
{
|
||||
case 1:
|
||||
if (!type->isNullable())
|
||||
{
|
||||
serialization->deserializeBinary(min_val, istr);
|
||||
serialization->deserializeBinary(max_val, istr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// NOTE: that this serialization differs from
|
||||
/// IMergeTreeDataPart::MinMaxIndex::load() to preserve
|
||||
/// backward compatibility.
|
||||
///
|
||||
/// But this is deprecated format, so this is OK.
|
||||
|
||||
bool is_null;
|
||||
readBinary(is_null, istr);
|
||||
if (!is_null)
|
||||
{
|
||||
serialization->deserializeBinary(min_val, istr);
|
||||
serialization->deserializeBinary(max_val, istr);
|
||||
}
|
||||
else
|
||||
{
|
||||
min_val = Null();
|
||||
max_val = Null();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/// New format with proper Nullable support for values that includes Null values
|
||||
case 2:
|
||||
serialization->deserializeBinary(min_val, istr);
|
||||
serialization->deserializeBinary(max_val, istr);
|
||||
}
|
||||
else
|
||||
{
|
||||
min_val = Null();
|
||||
max_val = Null();
|
||||
}
|
||||
|
||||
// NULL_LAST
|
||||
if (min_val.isNull())
|
||||
min_val = PositiveInfinity();
|
||||
if (max_val.isNull())
|
||||
max_val = PositiveInfinity();
|
||||
|
||||
break;
|
||||
default:
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown index version {}.", version);
|
||||
}
|
||||
|
||||
hyperrectangle.emplace_back(min_val, true, max_val, true);
|
||||
}
|
||||
}
|
||||
@ -203,6 +211,15 @@ bool MergeTreeIndexMinMax::mayBenefitFromIndexForIn(const ASTPtr & node) const
|
||||
return false;
|
||||
}
|
||||
|
||||
MergeTreeIndexFormat MergeTreeIndexMinMax::getDeserializedFormat(const DiskPtr disk, const std::string & relative_path_prefix) const
|
||||
{
|
||||
if (disk->exists(relative_path_prefix + ".idx2"))
|
||||
return {2, ".idx2"};
|
||||
else if (disk->exists(relative_path_prefix + ".idx"))
|
||||
return {1, ".idx"};
|
||||
return {0 /* unknown */, ""};
|
||||
}
|
||||
|
||||
MergeTreeIndexPtr minmaxIndexCreator(
|
||||
const IndexDescription & index)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ struct MergeTreeIndexGranuleMinMax final : public IMergeTreeIndexGranule
|
||||
~MergeTreeIndexGranuleMinMax() override = default;
|
||||
|
||||
void serializeBinary(WriteBuffer & ostr) const override;
|
||||
void deserializeBinary(ReadBuffer & istr) override;
|
||||
void deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version) override;
|
||||
|
||||
bool empty() const override { return hyperrectangle.empty(); }
|
||||
|
||||
@ -81,6 +81,9 @@ public:
|
||||
const SelectQueryInfo & query, ContextPtr context) const override;
|
||||
|
||||
bool mayBenefitFromIndexForIn(const ASTPtr & node) const override;
|
||||
|
||||
const char* getSerializedFileExtension() const override { return ".idx2"; }
|
||||
MergeTreeIndexFormat getDeserializedFormat(const DiskPtr disk, const std::string & path_prefix) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,29 @@
|
||||
#include <Storages/MergeTree/MergeTreeIndexReader.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace DB;
|
||||
|
||||
std::unique_ptr<MergeTreeReaderStream> makeIndexReader(
|
||||
const std::string & extension,
|
||||
MergeTreeIndexPtr index,
|
||||
MergeTreeData::DataPartPtr part,
|
||||
size_t marks_count,
|
||||
const MarkRanges & all_mark_ranges,
|
||||
MergeTreeReaderSettings settings)
|
||||
{
|
||||
return std::make_unique<MergeTreeReaderStream>(
|
||||
part->volume->getDisk(),
|
||||
part->getFullRelativePath() + index->getFileName(), extension, marks_count,
|
||||
all_mark_ranges,
|
||||
std::move(settings), nullptr, nullptr,
|
||||
part->getFileSizeOrZero(index->getFileName() + extension),
|
||||
&part->index_granularity_info,
|
||||
ReadBufferFromFileBase::ProfileCallback{}, CLOCK_MONOTONIC_COARSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -7,27 +31,28 @@ namespace DB
|
||||
MergeTreeIndexReader::MergeTreeIndexReader(
|
||||
MergeTreeIndexPtr index_, MergeTreeData::DataPartPtr part_, size_t marks_count_, const MarkRanges & all_mark_ranges_,
|
||||
MergeTreeReaderSettings settings)
|
||||
: index(index_), stream(
|
||||
part_->volume->getDisk(),
|
||||
part_->getFullRelativePath() + index->getFileName(), ".idx", marks_count_,
|
||||
all_mark_ranges_,
|
||||
std::move(settings), nullptr, nullptr,
|
||||
part_->getFileSizeOrZero(index->getFileName() + ".idx"),
|
||||
&part_->index_granularity_info,
|
||||
ReadBufferFromFileBase::ProfileCallback{}, CLOCK_MONOTONIC_COARSE)
|
||||
: index(index_)
|
||||
{
|
||||
stream.seekToStart();
|
||||
const std::string & path_prefix = part_->getFullRelativePath() + index->getFileName();
|
||||
auto index_format = index->getDeserializedFormat(part_->volume->getDisk(), path_prefix);
|
||||
|
||||
stream = makeIndexReader(index_format.extension, index_, part_, marks_count_, all_mark_ranges_, std::move(settings));
|
||||
version = index_format.version;
|
||||
|
||||
stream->seekToStart();
|
||||
}
|
||||
|
||||
MergeTreeIndexReader::~MergeTreeIndexReader() = default;
|
||||
|
||||
void MergeTreeIndexReader::seek(size_t mark)
|
||||
{
|
||||
stream.seekToMark(mark);
|
||||
stream->seekToMark(mark);
|
||||
}
|
||||
|
||||
MergeTreeIndexGranulePtr MergeTreeIndexReader::read()
|
||||
{
|
||||
auto granule = index->createIndexGranule();
|
||||
granule->deserializeBinary(*stream.data_buffer);
|
||||
granule->deserializeBinary(*stream->data_buffer, version);
|
||||
return granule;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <Storages/MergeTree/MergeTreeReaderStream.h>
|
||||
#include <Storages/MergeTree/MergeTreeIndices.h>
|
||||
#include <Storages/MergeTree/MergeTreeData.h>
|
||||
@ -16,6 +17,7 @@ public:
|
||||
size_t marks_count_,
|
||||
const MarkRanges & all_mark_ranges_,
|
||||
MergeTreeReaderSettings settings);
|
||||
~MergeTreeIndexReader();
|
||||
|
||||
void seek(size_t mark);
|
||||
|
||||
@ -23,7 +25,8 @@ public:
|
||||
|
||||
private:
|
||||
MergeTreeIndexPtr index;
|
||||
MergeTreeReaderStream stream;
|
||||
std::unique_ptr<MergeTreeReaderStream> stream;
|
||||
uint8_t version = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -48,8 +48,7 @@ MergeTreeIndexGranuleSet::MergeTreeIndexGranuleSet(
|
||||
void MergeTreeIndexGranuleSet::serializeBinary(WriteBuffer & ostr) const
|
||||
{
|
||||
if (empty())
|
||||
throw Exception(
|
||||
"Attempt to write empty set index " + backQuote(index_name), ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Attempt to write empty set index {}.", backQuote(index_name));
|
||||
|
||||
const auto & size_type = DataTypePtr(std::make_shared<DataTypeUInt64>());
|
||||
auto size_serialization = size_type->getDefaultSerialization();
|
||||
@ -80,8 +79,11 @@ void MergeTreeIndexGranuleSet::serializeBinary(WriteBuffer & ostr) const
|
||||
}
|
||||
}
|
||||
|
||||
void MergeTreeIndexGranuleSet::deserializeBinary(ReadBuffer & istr)
|
||||
void MergeTreeIndexGranuleSet::deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version)
|
||||
{
|
||||
if (version != 1)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown index version {}.", version);
|
||||
|
||||
block.clear();
|
||||
|
||||
Field field_rows;
|
||||
|
@ -28,7 +28,7 @@ struct MergeTreeIndexGranuleSet final : public IMergeTreeIndexGranule
|
||||
MutableColumns && columns_);
|
||||
|
||||
void serializeBinary(WriteBuffer & ostr) const override;
|
||||
void deserializeBinary(ReadBuffer & istr) override;
|
||||
void deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version) override;
|
||||
|
||||
size_t size() const { return block.rows(); }
|
||||
bool empty() const override { return !size(); }
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <Core/Block.h>
|
||||
#include <Storages/StorageInMemoryMetadata.h>
|
||||
#include <Storages/MergeTree/MergeTreeDataPartChecksum.h>
|
||||
@ -17,13 +18,37 @@ constexpr auto INDEX_FILE_PREFIX = "skp_idx_";
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using MergeTreeIndexVersion = uint8_t;
|
||||
struct MergeTreeIndexFormat
|
||||
{
|
||||
MergeTreeIndexVersion version;
|
||||
const char* extension;
|
||||
|
||||
operator bool() const { return version != 0; }
|
||||
};
|
||||
|
||||
/// Stores some info about a single block of data.
|
||||
struct IMergeTreeIndexGranule
|
||||
{
|
||||
virtual ~IMergeTreeIndexGranule() = default;
|
||||
|
||||
/// Serialize always last version.
|
||||
virtual void serializeBinary(WriteBuffer & ostr) const = 0;
|
||||
virtual void deserializeBinary(ReadBuffer & istr) = 0;
|
||||
|
||||
/// Version of the index to deserialize:
|
||||
///
|
||||
/// - 2 -- minmax index for proper Nullable support,
|
||||
/// - 1 -- everything else.
|
||||
///
|
||||
/// Implementation is responsible for version check,
|
||||
/// and throw LOGICAL_ERROR in case of unsupported version.
|
||||
///
|
||||
/// See also:
|
||||
/// - IMergeTreeIndex::getSerializedFileExtension()
|
||||
/// - IMergeTreeIndex::getDeserializedFormat()
|
||||
/// - MergeTreeDataMergerMutator::collectFilesToSkip()
|
||||
/// - MergeTreeDataMergerMutator::collectFilesForRenames()
|
||||
virtual void deserializeBinary(ReadBuffer & istr, MergeTreeIndexVersion version) = 0;
|
||||
|
||||
virtual bool empty() const = 0;
|
||||
};
|
||||
@ -73,9 +98,26 @@ struct IMergeTreeIndex
|
||||
|
||||
virtual ~IMergeTreeIndex() = default;
|
||||
|
||||
/// gets filename without extension
|
||||
/// Returns filename without extension.
|
||||
String getFileName() const { return INDEX_FILE_PREFIX + index.name; }
|
||||
|
||||
/// Returns extension for serialization.
|
||||
/// Reimplement if you want new index format.
|
||||
///
|
||||
/// NOTE: In case getSerializedFileExtension() is reimplemented,
|
||||
/// getDeserializedFormat() should be reimplemented too,
|
||||
/// and check all previous extensions too
|
||||
/// (to avoid breaking backward compatibility).
|
||||
virtual const char* getSerializedFileExtension() const { return ".idx"; }
|
||||
|
||||
/// Returns extension for deserialization.
|
||||
///
|
||||
/// Return pair<extension, version>.
|
||||
virtual MergeTreeIndexFormat getDeserializedFormat(const DiskPtr, const std::string & /* relative_path_prefix */) const
|
||||
{
|
||||
return {1, ".idx"};
|
||||
}
|
||||
|
||||
/// Checks whether the column is in data skipping index.
|
||||
virtual bool mayBenefitFromIndexForIn(const ASTPtr & node) const = 0;
|
||||
|
||||
|
@ -959,9 +959,19 @@ std::shared_ptr<StorageMergeTree::MergeMutateSelectedEntry> StorageMergeTree::se
|
||||
|
||||
if (!commands_for_size_validation.empty())
|
||||
{
|
||||
MutationsInterpreter interpreter(
|
||||
shared_from_this(), metadata_snapshot, commands_for_size_validation, getContext(), false);
|
||||
commands_size += interpreter.evaluateCommandsSize();
|
||||
try
|
||||
{
|
||||
MutationsInterpreter interpreter(
|
||||
shared_from_this(), metadata_snapshot, commands_for_size_validation, getContext(), false);
|
||||
commands_size += interpreter.evaluateCommandsSize();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
MergeTreeMutationEntry & entry = it->second;
|
||||
entry.latest_fail_time = time(nullptr);
|
||||
entry.latest_fail_reason = getCurrentExceptionMessage(false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_ast_elements + commands_size >= max_ast_elements)
|
||||
@ -971,17 +981,21 @@ std::shared_ptr<StorageMergeTree::MergeMutateSelectedEntry> StorageMergeTree::se
|
||||
commands.insert(commands.end(), it->second.commands.begin(), it->second.commands.end());
|
||||
}
|
||||
|
||||
auto new_part_info = part->info;
|
||||
new_part_info.mutation = current_mutations_by_version.rbegin()->first;
|
||||
if (!commands.empty())
|
||||
{
|
||||
auto new_part_info = part->info;
|
||||
new_part_info.mutation = current_mutations_by_version.rbegin()->first;
|
||||
|
||||
future_part.parts.push_back(part);
|
||||
future_part.part_info = new_part_info;
|
||||
future_part.name = part->getNewName(new_part_info);
|
||||
future_part.type = part->getType();
|
||||
future_part.parts.push_back(part);
|
||||
future_part.part_info = new_part_info;
|
||||
future_part.name = part->getNewName(new_part_info);
|
||||
future_part.type = part->getType();
|
||||
|
||||
tagger = std::make_unique<CurrentlyMergingPartsTagger>(future_part, MergeTreeDataMergerMutator::estimateNeededDiskSpace({part}), *this, metadata_snapshot, true);
|
||||
return std::make_shared<MergeMutateSelectedEntry>(future_part, std::move(tagger), commands);
|
||||
tagger = std::make_unique<CurrentlyMergingPartsTagger>(future_part, MergeTreeDataMergerMutator::estimateNeededDiskSpace({part}), *this, metadata_snapshot, true);
|
||||
return std::make_shared<MergeMutateSelectedEntry>(future_part, std::move(tagger), commands);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -1036,6 +1050,7 @@ bool StorageMergeTree::scheduleDataProcessingJob(IBackgroundJobExecutor & execut
|
||||
|
||||
auto share_lock = lockForShare(RWLockImpl::NO_QUERY, getSettings()->lock_acquire_timeout_for_background_operations);
|
||||
|
||||
bool has_mutations;
|
||||
{
|
||||
std::unique_lock lock(currently_processing_in_background_mutex);
|
||||
if (merger_mutator.merges_blocker.isCancelled())
|
||||
@ -1044,6 +1059,15 @@ bool StorageMergeTree::scheduleDataProcessingJob(IBackgroundJobExecutor & execut
|
||||
merge_entry = selectPartsToMerge(metadata_snapshot, false, {}, false, nullptr, share_lock, lock);
|
||||
if (!merge_entry)
|
||||
mutate_entry = selectPartsToMutate(metadata_snapshot, nullptr, share_lock);
|
||||
|
||||
has_mutations = !current_mutations_by_version.empty();
|
||||
}
|
||||
|
||||
if (!mutate_entry && has_mutations)
|
||||
{
|
||||
/// Notify in case of errors
|
||||
std::lock_guard lock(mutation_wait_mutex);
|
||||
mutation_wait_event.notify_all();
|
||||
}
|
||||
|
||||
if (merge_entry)
|
||||
|
@ -141,6 +141,7 @@ SRCS(
|
||||
StorageMerge.cpp
|
||||
StorageMergeTree.cpp
|
||||
StorageMongoDB.cpp
|
||||
StorageMongoDBSocketFactory.cpp
|
||||
StorageMySQL.cpp
|
||||
StorageNull.cpp
|
||||
StorageReplicatedMergeTree.cpp
|
||||
|
@ -647,9 +647,13 @@ def run_tests_array(all_tests_with_params):
|
||||
failures_chain += 1
|
||||
status += MSG_FAIL
|
||||
status += print_test_time(total_time)
|
||||
status += " - having exception:\n{}\n".format(
|
||||
status += " - having exception in stdout:\n{}\n".format(
|
||||
'\n'.join(stdout.split('\n')[:100]))
|
||||
status += 'Database: ' + testcase_args.testcase_database
|
||||
elif '@@SKIP@@' in stdout:
|
||||
skipped_total += 1
|
||||
skip_reason = stdout.replace('@@SKIP@@', '').rstrip("\n")
|
||||
status += MSG_SKIPPED + f" - {skip_reason}\n"
|
||||
elif reference_file is None:
|
||||
status += MSG_UNKNOWN
|
||||
status += print_test_time(total_time)
|
||||
|
@ -113,6 +113,7 @@ def assert_nested_table_is_created(table_name, materialized_database='test_datab
|
||||
assert(table_name in database_tables)
|
||||
|
||||
|
||||
@pytest.mark.timeout(320)
|
||||
def check_tables_are_synchronized(table_name, order_by='key', postgres_database='postgres_database', materialized_database='test_database'):
|
||||
assert_nested_table_is_created(table_name, materialized_database)
|
||||
|
||||
|
@ -1,284 +0,0 @@
|
||||
<test>
|
||||
<preconditions>
|
||||
<table_exists>hits_100m_single</table_exists>
|
||||
</preconditions>
|
||||
|
||||
<settings>
|
||||
<compile_aggregate_expressions>1</compile_aggregate_expressions>
|
||||
<min_count_to_compile_aggregate_expression>0</min_count_to_compile_aggregate_expression>
|
||||
</settings>
|
||||
|
||||
<create_query>
|
||||
CREATE TABLE jit_test_memory (
|
||||
key UInt64,
|
||||
value_1 UInt64,
|
||||
value_2 UInt64,
|
||||
value_3 UInt64,
|
||||
value_4 UInt64,
|
||||
value_5 UInt64,
|
||||
predicate UInt8
|
||||
) Engine = Memory
|
||||
</create_query>
|
||||
|
||||
<create_query>
|
||||
CREATE TABLE jit_test_merge_tree (
|
||||
key UInt64,
|
||||
value_1 UInt64,
|
||||
value_2 UInt64,
|
||||
value_3 UInt64,
|
||||
value_4 UInt64,
|
||||
value_5 UInt64,
|
||||
predicate UInt8
|
||||
) Engine = MergeTree
|
||||
ORDER BY key
|
||||
</create_query>
|
||||
|
||||
<create_query>
|
||||
CREATE TABLE jit_test_merge_tree_nullable (
|
||||
key UInt64,
|
||||
value_1 Nullable(UInt64),
|
||||
value_2 Nullable(UInt64),
|
||||
value_3 Nullable(UInt64),
|
||||
value_4 Nullable(UInt64),
|
||||
value_5 Nullable(UInt64),
|
||||
predicate UInt8
|
||||
) Engine = Memory
|
||||
</create_query>
|
||||
|
||||
<create_query>
|
||||
CREATE TABLE jit_test_memory_nullable (
|
||||
key UInt64,
|
||||
value_1 Nullable(UInt64),
|
||||
value_2 Nullable(UInt64),
|
||||
value_3 Nullable(UInt64),
|
||||
value_4 Nullable(UInt64),
|
||||
value_5 Nullable(UInt64),
|
||||
predicate UInt8
|
||||
) Engine = MergeTree
|
||||
ORDER BY key
|
||||
</create_query>
|
||||
|
||||
<substitutions>
|
||||
<substitution>
|
||||
<name>function</name>
|
||||
<values>
|
||||
<value>sum</value>
|
||||
<value>min</value>
|
||||
<value>max</value>
|
||||
<value>avg</value>
|
||||
<value>any</value>
|
||||
<value>anyLast</value>
|
||||
<value>count</value>
|
||||
<value>groupBitOr</value>
|
||||
<value>groupBitAnd</value>
|
||||
<value>groupBitXor</value>
|
||||
</values>
|
||||
</substitution>
|
||||
|
||||
<substitution>
|
||||
<name>table</name>
|
||||
<values>
|
||||
<value>jit_test_memory</value>
|
||||
<value>jit_test_merge_tree</value>
|
||||
<value>jit_test_memory_nullable</value>
|
||||
<value>jit_test_merge_tree_nullable</value>
|
||||
</values>
|
||||
</substitution>
|
||||
|
||||
<substitution>
|
||||
<name>group_scale</name>
|
||||
<values>
|
||||
<value>1000000</value>
|
||||
</values>
|
||||
</substitution>
|
||||
</substitutions>
|
||||
|
||||
<fill_query>
|
||||
INSERT INTO {table}
|
||||
SELECT
|
||||
number % 1000000,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
if (number % 2 == 0, 1, 0)
|
||||
FROM
|
||||
system.numbers_mt
|
||||
LIMIT 10000000
|
||||
</fill_query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(value_1),
|
||||
{function}(value_2),
|
||||
{function}(value_3)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(value_1),
|
||||
{function}(value_2),
|
||||
sum(toUInt256(value_3)),
|
||||
{function}(value_3)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}If(value_1, predicate),
|
||||
{function}If(value_2, predicate),
|
||||
{function}If(value_3, predicate)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}If(value_1, predicate),
|
||||
{function}If(value_2, predicate),
|
||||
sumIf(toUInt256(value_3), predicate),
|
||||
{function}If(value_3, predicate)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(value_1),
|
||||
{function}(value_2),
|
||||
{function}(value_3),
|
||||
{function}(value_4),
|
||||
{function}(value_5)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(value_1),
|
||||
{function}(value_2),
|
||||
sum(toUInt256(value_3)),
|
||||
{function}(value_3),
|
||||
{function}(value_4),
|
||||
{function}(value_5)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}If(value_1, predicate),
|
||||
{function}If(value_2, predicate),
|
||||
{function}If(value_3, predicate),
|
||||
{function}If(value_4, predicate),
|
||||
{function}If(value_5, predicate)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}If(value_1, predicate),
|
||||
{function}If(value_2, predicate),
|
||||
sumIf(toUInt256(value_3), predicate),
|
||||
{function}If(value_3, predicate),
|
||||
{function}If(value_4, predicate),
|
||||
{function}If(value_5, predicate)
|
||||
FROM {table}
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(WatchID),
|
||||
{function}(CounterID),
|
||||
{function}(ClientIP)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(WatchID),
|
||||
{function}(CounterID),
|
||||
sum(toUInt256(ClientIP)),
|
||||
{function}(ClientIP)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(WatchID),
|
||||
{function}(CounterID),
|
||||
{function}(ClientIP),
|
||||
{function}(IPNetworkID),
|
||||
{function}(SearchEngineID)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
SELECT
|
||||
{function}(WatchID),
|
||||
{function}(CounterID),
|
||||
sum(toUInt256(ClientIP)),
|
||||
{function}(ClientIP),
|
||||
{function}(IPNetworkID),
|
||||
{function}(SearchEngineID)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
WITH (WatchID % 2 == 0) AS predicate
|
||||
SELECT
|
||||
{function}If(WatchID, predicate),
|
||||
{function}If(CounterID, predicate),
|
||||
{function}If(ClientIP, predicate)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
WITH (WatchID % 2 == 0) AS predicate
|
||||
SELECT
|
||||
{function}If(WatchID, predicate),
|
||||
{function}If(CounterID, predicate),
|
||||
sumIf(toUInt256(ClientIP), predicate),
|
||||
{function}If(ClientIP, predicate)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
WITH (WatchID % 2 == 0) AS predicate
|
||||
SELECT
|
||||
{function}If(WatchID, predicate),
|
||||
{function}If(CounterID, predicate),
|
||||
{function}If(ClientIP, predicate),
|
||||
{function}If(IPNetworkID, predicate),
|
||||
{function}If(SearchEngineID, predicate)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<query>
|
||||
WITH (WatchID % 2 == 0) AS predicate
|
||||
SELECT
|
||||
{function}If(WatchID, predicate),
|
||||
{function}If(CounterID, predicate),
|
||||
sumIf(toUInt256(ClientIP), predicate),
|
||||
{function}If(ClientIP, predicate),
|
||||
{function}If(IPNetworkID, predicate),
|
||||
{function}If(SearchEngineID, predicate)
|
||||
FROM hits_100m_single
|
||||
FORMAT Null
|
||||
</query>
|
||||
|
||||
<drop_query>DROP TABLE IF EXISTS {table}</drop_query>
|
||||
</test>
|
@ -6,10 +6,15 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
|
||||
# If we run sanitized binary under qemu, it will try to slowly allocate 20 TiB until OOM.
|
||||
# Don't even try to do that. This test should be disabled for sanitizer builds.
|
||||
${CLICKHOUSE_LOCAL} --query "SELECT max(value LIKE '%sanitize%') FROM system.build_options" | grep -q '1' && echo 'Skip test for sanitizer build' && exit
|
||||
${CLICKHOUSE_LOCAL} --query "SELECT max(value LIKE '%sanitize%') FROM system.build_options" | grep -q '1' && echo '@@SKIP@@: Sanitizer build' && exit
|
||||
|
||||
command=$(command -v ${CLICKHOUSE_LOCAL})
|
||||
|
||||
if ! hash qemu-x86_64-static 2>/dev/null; then
|
||||
echo "@@SKIP@@: No qemu-x86_64-static"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
function run_with_cpu()
|
||||
{
|
||||
qemu-x86_64-static -cpu "$@" "$command" --query "SELECT 1" 2>&1 | grep -v -F "warning: TCG doesn't support requested feature" ||:
|
||||
|
@ -12,7 +12,7 @@ expect_after {
|
||||
|
||||
set basedir [file dirname $argv0]
|
||||
spawn bash -c "source $basedir/../shell_config.sh ; \$MYSQL_CLIENT_BINARY \$MYSQL_CLIENT_OPT"
|
||||
expect "mysql> "
|
||||
expect -nocase -re "mysql.*> "
|
||||
|
||||
send -- "USE system;\r"
|
||||
expect "Database changed"
|
||||
@ -41,8 +41,7 @@ expect "+---------------+-------------+"
|
||||
expect "| 10 | 45 |"
|
||||
expect "+---------------+-------------+"
|
||||
expect "1 row in set"
|
||||
expect "Read 10 rows, 80.00 B"
|
||||
expect "mysql> "
|
||||
expect -nocase -re "mysql.*> "
|
||||
|
||||
send -- "quit;\r"
|
||||
expect eof
|
||||
|
@ -49,15 +49,11 @@ SET force_primary_key = 0;
|
||||
SELECT * FROM nullable_minmax_index ORDER BY k;
|
||||
SET max_rows_to_read = 6;
|
||||
SELECT * FROM nullable_minmax_index WHERE v IS NULL;
|
||||
-- NOTE: granuals with Null values cannot be filtred in data skipping indexes,
|
||||
-- due to backward compatibility
|
||||
SET max_rows_to_read = 0;
|
||||
SET max_rows_to_read = 8;
|
||||
SELECT * FROM nullable_minmax_index WHERE v IS NOT NULL;
|
||||
SET max_rows_to_read = 6;
|
||||
SELECT * FROM nullable_minmax_index WHERE v > 2;
|
||||
-- NOTE: granuals with Null values cannot be filtred in data skipping indexes,
|
||||
-- due to backward compatibility
|
||||
SET max_rows_to_read = 0;
|
||||
SET max_rows_to_read = 4;
|
||||
SELECT * FROM nullable_minmax_index WHERE v <= 2;
|
||||
|
||||
DROP TABLE nullable_key;
|
||||
|
@ -0,0 +1,3 @@
|
||||
Started
|
||||
Sent kill request
|
||||
Exit 138
|
36
tests/queries/0_stateless/01572_kill_window_function.sh
Executable file
36
tests/queries/0_stateless/01572_kill_window_function.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
# Run a test query that takes very long to run.
|
||||
query_id="01572_kill_window_function-$CLICKHOUSE_DATABASE"
|
||||
$CLICKHOUSE_CLIENT --query_id="$query_id" --query "SELECT count(1048575) OVER (PARTITION BY intDiv(NULL, number) ORDER BY number DESC NULLS FIRST ROWS BETWEEN CURRENT ROW AND 1048575 FOLLOWING) FROM numbers(255, 1048575)" >/dev/null 2>&1 &
|
||||
client_pid=$!
|
||||
echo Started
|
||||
|
||||
# Use one query to both kill the test query and verify that it has started,
|
||||
# because if we try to kill it before it starts, the test will fail.
|
||||
while [ -z "$($CLICKHOUSE_CLIENT --query "kill query where query_id = '$query_id' and current_database = currentDatabase()")" ]
|
||||
do
|
||||
# If we don't yet see the query in the process list, the client should still
|
||||
# be running. The query is very long.
|
||||
kill -0 -- $client_pid
|
||||
sleep 1
|
||||
done
|
||||
echo Sent kill request
|
||||
|
||||
# Wait for the client to terminate.
|
||||
client_exit_code=0
|
||||
wait $client_pid || client_exit_code=$?
|
||||
|
||||
echo "Exit $client_exit_code"
|
||||
|
||||
# We have tested for Ctrl+C.
|
||||
# The following client flags don't cancel, but should: --max_execution_time,
|
||||
# --receive_timeout. Probably needs asynchonous calculation of query limits, as
|
||||
# discussed with Nikolay on TG: https://t.me/c/1214350934/21492
|
||||
|
@ -7,6 +7,15 @@ CUR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CUR_DIR"/../shell_config.sh
|
||||
|
||||
if [[ -z $S3_ACCESS_KEY_ID ]]; then
|
||||
echo "@@SKIP@@: Missing \$S3_ACCESS_KEY_ID"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z $S3_SECRET_ACCESS ]]; then
|
||||
echo "@@SKIP@@: Missing \$S3_SECRET_ACCESS"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
${CLICKHOUSE_CLIENT_BINARY} --send_logs_level="none" -q "SELECT * FROM s3('https://s3.mds.yandex.net/clickhouse-test-reports/*/*/functional_stateless_tests_(ubsan)/test_results.tsv', '$S3_ACCESS_KEY_ID', '$S3_SECRET_ACCESS', 'LineAsString', 'line String') limit 100 FORMAT Null;"
|
||||
${CLICKHOUSE_CLIENT_BINARY} --send_logs_level="none" -q "SELECT * FROM s3Cluster('test_cluster_two_shards', 'https://s3.mds.yandex.net/clickhouse-test-reports/*/*/functional_stateless_tests_(ubsan)/test_results.tsv', '$S3_ACCESS_KEY_ID', '$S3_SECRET_ACCESS', 'LineAsString', 'line String') limit 100 FORMAT Null;"
|
||||
|
@ -0,0 +1,20 @@
|
||||
Row 1:
|
||||
──────
|
||||
toUnixTimestamp(t): 14459031
|
||||
timeZoneOffset(t): -2670
|
||||
formatDateTime(t, '%F %T', 'Africa/Monrovia'): 1970-06-17 07:39:21
|
||||
toString(t, 'Africa/Monrovia'): 1970-06-17 07:39:21
|
||||
toStartOfMinute(t): 1970-06-17 07:39:00
|
||||
toStartOfFiveMinute(t): 1970-06-17 07:35:00
|
||||
toStartOfFifteenMinutes(t): 1970-06-17 07:30:00
|
||||
toStartOfTenMinutes(t): 1970-06-17 07:30:00
|
||||
toStartOfHour(t): 1970-06-17 07:00:00
|
||||
toStartOfDay(t): 1970-06-17 00:00:00
|
||||
toStartOfWeek(t): 1970-06-14
|
||||
toStartOfInterval(t, toIntervalSecond(1)): 1970-06-17 07:39:21
|
||||
toStartOfInterval(t, toIntervalMinute(1)): 1970-06-17 07:39:00
|
||||
toStartOfInterval(t, toIntervalMinute(2)): 1970-06-17 07:38:00
|
||||
toStartOfInterval(t, toIntervalMinute(5)): 1970-06-17 07:35:00
|
||||
toStartOfInterval(t, toIntervalMinute(60)): 1970-06-17 07:00:00
|
||||
addMinutes(t, 1): 1970-06-17 07:40:21
|
||||
addMinutes(t, 60): 1970-06-17 08:39:21
|
21
tests/queries/0_stateless/01958_partial_hour_timezone.sql
Normal file
21
tests/queries/0_stateless/01958_partial_hour_timezone.sql
Normal file
@ -0,0 +1,21 @@
|
||||
-- Appeared in https://github.com/ClickHouse/ClickHouse/pull/26978#issuecomment-890889362
|
||||
WITH toDateTime('1970-06-17 07:39:21', 'Africa/Monrovia') as t
|
||||
SELECT toUnixTimestamp(t),
|
||||
timeZoneOffset(t),
|
||||
formatDateTime(t, '%F %T', 'Africa/Monrovia'),
|
||||
toString(t, 'Africa/Monrovia'),
|
||||
toStartOfMinute(t),
|
||||
toStartOfFiveMinute(t),
|
||||
toStartOfFifteenMinutes(t),
|
||||
toStartOfTenMinutes(t),
|
||||
toStartOfHour(t),
|
||||
toStartOfDay(t),
|
||||
toStartOfWeek(t),
|
||||
toStartOfInterval(t, INTERVAL 1 second),
|
||||
toStartOfInterval(t, INTERVAL 1 minute),
|
||||
toStartOfInterval(t, INTERVAL 2 minute),
|
||||
toStartOfInterval(t, INTERVAL 5 minute),
|
||||
toStartOfInterval(t, INTERVAL 60 minute),
|
||||
addMinutes(t, 1),
|
||||
addMinutes(t, 60)
|
||||
FORMAT Vertical;
|
40
tests/queries/0_stateless/02003_memory_limit_in_client.expect
Executable file
40
tests/queries/0_stateless/02003_memory_limit_in_client.expect
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/expect -f
|
||||
|
||||
# This is a test for system.warnings. Testing in interactive mode is necessary,
|
||||
# as we want to see certain warnings from client
|
||||
|
||||
log_user 0
|
||||
set timeout 60
|
||||
match_max 100000
|
||||
|
||||
# A default timeout action is to do nothing, change it to fail
|
||||
expect_after {
|
||||
timeout {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
set basedir [file dirname $argv0]
|
||||
spawn bash -c "source $basedir/../shell_config.sh ; \$CLICKHOUSE_CLIENT_BINARY \$CLICKHOUSE_CLIENT_OPT --disable_suggestion --max_memory_usage_in_client=1"
|
||||
expect ":) "
|
||||
|
||||
send -- "SELECT arrayMap(x -> range(x), range(number)) FROM numbers(1000)\r"
|
||||
expect "Code: 241"
|
||||
|
||||
expect ":) "
|
||||
|
||||
# Exit.
|
||||
send -- "\4"
|
||||
expect eof
|
||||
|
||||
set basedir [file dirname $argv0]
|
||||
spawn bash -c "source $basedir/../shell_config.sh ; \$CLICKHOUSE_CLIENT_BINARY \$CLICKHOUSE_CLIENT_OPT --disable_suggestion --max_memory_usage_in_client=1"
|
||||
expect ":) "
|
||||
|
||||
send -- "SELECT * FROM (SELECT * FROM system.numbers LIMIT 600000) as num WHERE num.number=60000\r"
|
||||
expect "60000"
|
||||
expect ":) "
|
||||
|
||||
# Exit.
|
||||
send -- "\4"
|
||||
expect eof
|
@ -0,0 +1,33 @@
|
||||
SET mutations_sync=2;
|
||||
|
||||
DROP TABLE IF EXISTS rep_data;
|
||||
CREATE TABLE rep_data
|
||||
(
|
||||
p Int,
|
||||
t DateTime,
|
||||
INDEX idx t TYPE minmax GRANULARITY 1
|
||||
)
|
||||
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/rep_data', '1')
|
||||
PARTITION BY p
|
||||
ORDER BY t
|
||||
SETTINGS number_of_free_entries_in_pool_to_execute_mutation=0;
|
||||
INSERT INTO rep_data VALUES (1, now());
|
||||
ALTER TABLE rep_data MATERIALIZE INDEX idx IN PARTITION ID 'NO_SUCH_PART'; -- { serverError 248 }
|
||||
ALTER TABLE rep_data MATERIALIZE INDEX idx IN PARTITION ID '1';
|
||||
ALTER TABLE rep_data MATERIALIZE INDEX idx IN PARTITION ID '2';
|
||||
|
||||
DROP TABLE IF EXISTS data;
|
||||
CREATE TABLE data
|
||||
(
|
||||
p Int,
|
||||
t DateTime,
|
||||
INDEX idx t TYPE minmax GRANULARITY 1
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY p
|
||||
ORDER BY t
|
||||
SETTINGS number_of_free_entries_in_pool_to_execute_mutation=0;
|
||||
INSERT INTO data VALUES (1, now());
|
||||
ALTER TABLE data MATERIALIZE INDEX idx IN PARTITION ID 'NO_SUCH_PART'; -- { serverError 341 }
|
||||
ALTER TABLE data MATERIALIZE INDEX idx IN PARTITION ID '1';
|
||||
ALTER TABLE data MATERIALIZE INDEX idx IN PARTITION ID '2';
|
8
tests/queries/0_stateless/02007_join_use_nulls.reference
Normal file
8
tests/queries/0_stateless/02007_join_use_nulls.reference
Normal file
@ -0,0 +1,8 @@
|
||||
1 2 3 1 3
|
||||
1 UInt8 2 UInt8 3 Nullable(UInt8)
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 3 LowCardinality(Nullable(UInt8))
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 1 LowCardinality(Nullable(UInt8))
|
||||
1 UInt8 2 UInt8 3 Nullable(UInt8)
|
||||
1 UInt8 2 UInt8 1 Nullable(UInt8) 3 Nullable(UInt8)
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 3 LowCardinality(Nullable(UInt8))
|
||||
1 LowCardinality(UInt8) 2 LowCardinality(UInt8) 1 LowCardinality(Nullable(UInt8)) 3 LowCardinality(Nullable(UInt8))
|
11
tests/queries/0_stateless/02007_join_use_nulls.sql
Normal file
11
tests/queries/0_stateless/02007_join_use_nulls.sql
Normal file
@ -0,0 +1,11 @@
|
||||
SET join_use_nulls = 1;
|
||||
|
||||
SELECT *, d.* FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.id, toTypeName(d.id) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.id, toTypeName(d.id) , d.values, toTypeName(d.values) FROM ( SELECT 1 AS id, 2 AS value ) a SEMI LEFT JOIN ( SELECT 1 AS id, 3 AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.values, toTypeName(d.values) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
||||
SELECT id, toTypeName(id), value, toTypeName(value), d.id, toTypeName(d.id) , d.values, toTypeName(d.values) FROM ( SELECT toLowCardinality(1) AS id, toLowCardinality(2) AS value ) a SEMI LEFT JOIN ( SELECT toLowCardinality(1) AS id, toLowCardinality(3) AS values ) AS d USING id;
|
@ -23,7 +23,7 @@ virtualenv build
|
||||
./build.py --skip-multi-page --skip-single-page --skip-amp --skip-pdf --skip-git-log --skip-docs --livereload 8080
|
||||
```
|
||||
|
||||
# How to quickly test the ugly annoying broken links in docs
|
||||
# How to quickly test the broken links in docs
|
||||
|
||||
```
|
||||
./build.py --skip-multi-page --skip-amp --skip-pdf --skip-blog --skip-git-log --lang en --livereload 8080
|
||||
|
Loading…
Reference in New Issue
Block a user