Merge remote-tracking branch 'upstream/master' into fix-projection-merge

This commit is contained in:
jsc0218 2024-08-20 13:19:23 +00:00
commit 1c53a02e4c
304 changed files with 2789 additions and 1598 deletions

View File

@ -482,7 +482,7 @@ jobs:
if: ${{ !failure() }} if: ${{ !failure() }}
run: | run: |
# update overall ci report # update overall ci report
python3 finish_check.py --wf-status ${{ contains(needs.*.result, 'failure') && 'failure' || 'success' }} python3 ./tests/ci/finish_check.py --wf-status ${{ contains(needs.*.result, 'failure') && 'failure' || 'success' }}
- name: Check Workflow results - name: Check Workflow results
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
run: | run: |
@ -490,5 +490,4 @@ jobs:
cat > "$WORKFLOW_RESULT_FILE" << 'EOF' cat > "$WORKFLOW_RESULT_FILE" << 'EOF'
${{ toJson(needs) }} ${{ toJson(needs) }}
EOF EOF
python3 ./tests/ci/ci_buddy.py --check-wf-status python3 ./tests/ci/ci_buddy.py --check-wf-status

2
.gitmodules vendored
View File

@ -108,7 +108,7 @@
url = https://github.com/ClickHouse/icudata url = https://github.com/ClickHouse/icudata
[submodule "contrib/icu"] [submodule "contrib/icu"]
path = contrib/icu path = contrib/icu
url = https://github.com/unicode-org/icu url = https://github.com/ClickHouse/icu
[submodule "contrib/flatbuffers"] [submodule "contrib/flatbuffers"]
path = contrib/flatbuffers path = contrib/flatbuffers
url = https://github.com/ClickHouse/flatbuffers url = https://github.com/ClickHouse/flatbuffers

View File

@ -1,4 +1,5 @@
### Table of Contents ### Table of Contents
**[ClickHouse release v24.8 LTS, 2024-08-20](#243)**<br/>
**[ClickHouse release v24.7, 2024-07-30](#247)**<br/> **[ClickHouse release v24.7, 2024-07-30](#247)**<br/>
**[ClickHouse release v24.6, 2024-07-01](#246)**<br/> **[ClickHouse release v24.6, 2024-07-01](#246)**<br/>
**[ClickHouse release v24.5, 2024-05-30](#245)**<br/> **[ClickHouse release v24.5, 2024-05-30](#245)**<br/>
@ -10,6 +11,153 @@
# 2024 Changelog # 2024 Changelog
### <a id="248"></a> ClickHouse release 24.8 LTS, 2024-08-20
#### Backward Incompatible Change
* `clickhouse-client` and `clickhouse-local` now default to multi-query mode (instead single-query mode). As an example, `clickhouse-client -q "SELECT 1; SELECT 2"` now works, whereas users previously had to add `--multiquery` (or `-n`). The `--multiquery/-n` switch became obsolete. INSERT queries in multi-query statements are treated specially based on their FORMAT clause: If the FORMAT is `VALUES` (the most common case), the end of the INSERT statement is represented by a trailing semicolon `;` at the end of the query. For all other FORMATs (e.g. `CSV` or `JSONEachRow`), the end of the INSERT statement is represented by two newlines `\n\n` at the end of the query. [#63898](https://github.com/ClickHouse/ClickHouse/pull/63898) ([FFish](https://github.com/wxybear)).
* In previous versions, it was possible to use an alternative syntax for `LowCardinality` data types by appending `WithDictionary` to the name of the data type. It was an initial working implementation, and it was never documented or exposed to the public. Now, it is deprecated. If you have used this syntax, you have to ALTER your tables and rename the data types to `LowCardinality`. [#66842](https://github.com/ClickHouse/ClickHouse/pull/66842) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Fix logical errors with storage `Buffer` used with distributed destination table. It's a backward incompatible change: queries using `Buffer` with a distributed destination table may stop working if the table appears more than once in the query (e.g., in a self-join). [#67015](https://github.com/ClickHouse/ClickHouse/pull/67015) ([vdimir](https://github.com/vdimir)).
* In previous versions, calling functions for random distributions based on the Gamma function (such as Chi-Squared, Student, Fisher) with negative arguments close to zero led to a long computation or an infinite loop. In the new version, calling these functions with zero or negative arguments will produce an exception. This closes [#67297](https://github.com/ClickHouse/ClickHouse/issues/67297). [#67326](https://github.com/ClickHouse/ClickHouse/pull/67326) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* The system table `text_log` is enabled by default. This is fully compatible with previous versions, but you may notice subtly increased disk usage on the local disk (this system table takes a tiny amount of disk space). [#67428](https://github.com/ClickHouse/ClickHouse/pull/67428) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* In previous versions, `arrayWithConstant` can be slow if asked to generate very large arrays. In the new version, it is limited to 1 GB per array. This closes [#32754](https://github.com/ClickHouse/ClickHouse/issues/32754). [#67741](https://github.com/ClickHouse/ClickHouse/pull/67741) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Fix REPLACE modifier formatting (forbid omitting brackets). [#67774](https://github.com/ClickHouse/ClickHouse/pull/67774) ([Azat Khuzhin](https://github.com/azat)).
* Backported in [#68349](https://github.com/ClickHouse/ClickHouse/issues/68349): Reimplement `Dynamic` type. Now when the limit of dynamic data types is reached new types are not casted to String but stored in a special data structure in binary format with binary encoded data type. Now any type ever inserted into `Dynamic` column can be read from it as subcolumn. [#68132](https://github.com/ClickHouse/ClickHouse/pull/68132) ([Kruglov Pavel](https://github.com/Avogar)).
#### New Feature
* Added a new `MergeTree` setting `deduplicate_merge_projection_mode` to control the projections during merges (for specific engines) and `OPTIMIZE DEDUPLICATE` query. Supported options: `throw` (throw an exception in case the projection is not fully supported for *MergeTree engine), `drop` (remove projection during merge if it can't be merged itself consistently) and `rebuild` (rebuild projection from scratch, which is a heavy operation). [#66672](https://github.com/ClickHouse/ClickHouse/pull/66672) ([jsc0218](https://github.com/jsc0218)).
* Add `_etag` virtual column for S3 table engine. Fixes [#65312](https://github.com/ClickHouse/ClickHouse/issues/65312). [#65386](https://github.com/ClickHouse/ClickHouse/pull/65386) ([skyoct](https://github.com/skyoct)).
* Added a tagging (namespace) mechanism for the query cache. The same queries with different tags are considered different by the query cache. Example: `SELECT 1 SETTINGS use_query_cache = 1, query_cache_tag = 'abc'` and `SELECT 1 SETTINGS use_query_cache = 1, query_cache_tag = 'def'` now create different query cache entries. [#68235](https://github.com/ClickHouse/ClickHouse/pull/68235) ([sakulali](https://github.com/sakulali)).
* Support more variants of JOIN strictness (`LEFT/RIGHT SEMI/ANTI/ANY JOIN`) with inequality conditions which involve columns from both left and right table. e.g. `t1.y < t2.y` (see the setting `allow_experimental_join_condition`). [#64281](https://github.com/ClickHouse/ClickHouse/pull/64281) ([lgbo](https://github.com/lgbo-ustc)).
* Intrpret Hive-style partitioning for different engines (`File`, `URL`, `S3`, `AzureBlobStorage`, `HDFS`). Hive-style partitioning organizes data into partitioned sub-directories, making it efficient to query and manage large datasets. Currently, it only creates virtual columns with the appropriate name and data. The follow-up PR will introduce the appropriate data filtering (performance speedup). [#65997](https://github.com/ClickHouse/ClickHouse/pull/65997) ([Yarik Briukhovetskyi](https://github.com/yariks5s)).
* Add function `printf` for Spark compatiability (but you can use the existing `format` function). [#66257](https://github.com/ClickHouse/ClickHouse/pull/66257) ([李扬](https://github.com/taiyang-li)).
* Added a new server setting, `disable_insertion_and_mutation`. If it is enabled, the server will deny all insertions and mutations. This includes asynchronous INSERTs. This setting can be used to create read-only replicas. [#66519](https://github.com/ClickHouse/ClickHouse/pull/66519) ([Xu Jia](https://github.com/XuJia0210)).
* Add options `restore_replace_external_engines_to_null` and `restore_replace_external_table_functions_to_null` to replace external engines and table_engines to `Null` engine that can be useful for testing. It should work for RESTORE and explicit table creation. [#66536](https://github.com/ClickHouse/ClickHouse/pull/66536) ([Ilya Yatsishin](https://github.com/qoega)).
* Added support for reading `MULTILINESTRING` geometry in `WKT` format using function `readWKTLineString`. [#67647](https://github.com/ClickHouse/ClickHouse/pull/67647) ([Jacob Reckhard](https://github.com/jacobrec)).
* Add a new table function `fuzzQuery`. This function allows the modification of a given query string with random variations. Example: `SELECT query FROM fuzzQuery('SELECT 1') LIMIT 5;`. [#67655](https://github.com/ClickHouse/ClickHouse/pull/67655) ([pufit](https://github.com/pufit)).
* Add a query `ALTER TABLE ... DROP DETACHED PARTITION ALL` to drop all detached partitions. [#67885](https://github.com/ClickHouse/ClickHouse/pull/67885) ([Duc Canh Le](https://github.com/canhld94)).
* Add the `rows_before_aggregation_at_least` statistic to the query response when a new setting, `rows_before_aggregation` is enabled. This statistic represents the number of rows read before aggregation. In the context of a distributed query, when using the `group by` or `max` aggregation function without a `limit`, `rows_before_aggregation_at_least` can reflect the number of rows hit by the query. [#66084](https://github.com/ClickHouse/ClickHouse/pull/66084) ([morning-color](https://github.com/morning-color)).
* Support `OPTIMIZE` query on `Join` tables to reduce their memory footprint. [#67883](https://github.com/ClickHouse/ClickHouse/pull/67883) ([Duc Canh Le](https://github.com/canhld94)).
* Allow run query instantly in play if you add `&run=1` in the URL [#66457](https://github.com/ClickHouse/ClickHouse/pull/66457) ([Aleksandr Musorin](https://github.com/AVMusorin)).
#### Experimental Feature
* Implement a new `JSON` data type. [#66444](https://github.com/ClickHouse/ClickHouse/pull/66444) ([Kruglov Pavel](https://github.com/Avogar)).
* Add the new `TimeSeries` table engine. [#64183](https://github.com/ClickHouse/ClickHouse/pull/64183) ([Vitaly Baranov](https://github.com/vitlibar)).
* Add new experimental `Kafka` storage engine to store offsets in Keeper instead of relying on committing them to Kafka. It makes the commit to ClickHouse tables atomic with regard to consumption from the queue. [#57625](https://github.com/ClickHouse/ClickHouse/pull/57625) ([János Benjamin Antal](https://github.com/antaljanosbenjamin)).
* Use adaptive read task size calculation method (adaptive meaning it depends on read column sizes) for parallel replicas. [#60377](https://github.com/ClickHouse/ClickHouse/pull/60377) ([Nikita Taranov](https://github.com/nickitat)).
* Added statistics type `count_min` (count-min sketches) which provide selectivity estimations for equality predicates like `col = 'val'`. Supported data types are string, date, datatime and numeric types. [#65521](https://github.com/ClickHouse/ClickHouse/pull/65521) ([JackyWoo](https://github.com/JackyWoo)).
#### Performance Improvement
* Setting `optimize_functions_to_subcolumns` is enabled by default. [#68053](https://github.com/ClickHouse/ClickHouse/pull/68053) ([Anton Popov](https://github.com/CurtizJ)).
* Store the `plain_rewritable` disk directory metadata in `__meta` layout, separately from the merge tree data in the object storage. Move the `plain_rewritable` disk to a flat directory structure. [#65751](https://github.com/ClickHouse/ClickHouse/pull/65751) ([Julia Kartseva](https://github.com/jkartseva)).
* Improve columns squashing (an operation happening in INSERT queries) for `String`/`Array`/`Map`/`Variant`/`Dynamic` types by reserving required memory in advance for all subcolumns. [#67043](https://github.com/ClickHouse/ClickHouse/pull/67043) ([Kruglov Pavel](https://github.com/Avogar)).
* Speed up `SYSTEM FLUSH LOGS` and flush logs on shutdown. [#67472](https://github.com/ClickHouse/ClickHouse/pull/67472) ([Sema Checherinda](https://github.com/CheSema)).
* Improved overall performance of merges by reducing the overhead of the scheduling steps of merges. [#68016](https://github.com/ClickHouse/ClickHouse/pull/68016) ([Anton Popov](https://github.com/CurtizJ)).
* Speed up tables removal for `DROP DATABASE` query, increased the default value for `database_catalog_drop_table_concurrency` to 16. [#67228](https://github.com/ClickHouse/ClickHouse/pull/67228) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
* Avoid allocating too much capacity for array column while writing ORC. Performance speeds up 15% for an Array column. [#67879](https://github.com/ClickHouse/ClickHouse/pull/67879) ([李扬](https://github.com/taiyang-li)).
* Speed up mutations for non-replicated MergeTree significantly [#66911](https://github.com/ClickHouse/ClickHouse/pull/66911) [#66909](https://github.com/ClickHouse/ClickHouse/pull/66909) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
#### Improvement
* Setting `allow_experimental_analyzer` is renamed to `enable_analyzer`. The old name is preserved in a form of an alias. This signifies that Analyzer is no longer in beta and is fully promoted to production. [#66438](https://github.com/ClickHouse/ClickHouse/pull/66438) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
* Improve schema inference of date times. Now DateTime64 used only when date time has fractional part, otherwise regular DateTime is used. Inference of Date/DateTime is more strict now, especially when `date_time_input_format='best_effort'` to avoid inferring date times from strings in corner cases. [#68382](https://github.com/ClickHouse/ClickHouse/pull/68382) ([Kruglov Pavel](https://github.com/Avogar)).
* ClickHouse server now supports new setting `max_keep_alive_requests`. For keep-alive HTTP connections to the server it works in tandem with `keep_alive_timeout` - if idle timeout not expired but there already more than `max_keep_alive_requests` requests done through the given connection - it will be closed by the server. [#61793](https://github.com/ClickHouse/ClickHouse/pull/61793) ([Nikita Taranov](https://github.com/nickitat)).
* Various improvements in the advanced dashboard. This closes [#67697](https://github.com/ClickHouse/ClickHouse/issues/67697). This closes [#63407](https://github.com/ClickHouse/ClickHouse/issues/63407). This closes [#51129](https://github.com/ClickHouse/ClickHouse/issues/51129). This closes [#61204](https://github.com/ClickHouse/ClickHouse/issues/61204). [#67701](https://github.com/ClickHouse/ClickHouse/pull/67701) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Do not require a grant for REMOTE when creating a Distributed table: a grant for the Distributed engine is enough. [#65419](https://github.com/ClickHouse/ClickHouse/pull/65419) ([jsc0218](https://github.com/jsc0218)).
* Do not pass logs for keeper explicitly in the Docker image to allow overriding. [#65564](https://github.com/ClickHouse/ClickHouse/pull/65564) ([Azat Khuzhin](https://github.com/azat)).
* Introduced `use_same_password_for_base_backup` settings for `BACKUP` and `RESTORE` queries, allowing to create and restore incremental backups to/from password protected archives. [#66214](https://github.com/ClickHouse/ClickHouse/pull/66214) ([Samuele](https://github.com/sguerrini97)).
* Ignore `async_load_databases` for `ATTACH` query (previously it was possible for ATTACH to return before the tables had been attached). [#66240](https://github.com/ClickHouse/ClickHouse/pull/66240) ([Azat Khuzhin](https://github.com/azat)).
* Added logs and metrics for rejected connections (where there are not enough resources). [#66410](https://github.com/ClickHouse/ClickHouse/pull/66410) ([Alexander Tokmakov](https://github.com/tavplubix)).
* Support proper `UUID` type for MongoDB engine. [#66671](https://github.com/ClickHouse/ClickHouse/pull/66671) ([Azat Khuzhin](https://github.com/azat)).
* Add replication lag and recovery time metrics. [#66703](https://github.com/ClickHouse/ClickHouse/pull/66703) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
* Add `DiskS3NoSuchKeyErrors` metric. [#66704](https://github.com/ClickHouse/ClickHouse/pull/66704) ([Miсhael Stetsyuk](https://github.com/mstetsyuk)).
* Ensure the `COMMENT` clause works for all table engines. [#66832](https://github.com/ClickHouse/ClickHouse/pull/66832) ([Joe Lynch](https://github.com/joelynch)).
* Function `mapFromArrays` now accepts `Map(K, V)` as first argument, for example: `SELECT mapFromArrays(map('a', 4, 'b', 4), ['aa', 'bb'])` now works and returns `{('a',4):'aa',('b',4):'bb'}`. Also, if the 1st argument is an Array, it can now also be of type `Array(Nullable(T))` or `Array(LowCardinality(Nullable(T)))` as long as the actual array values are not `NULL`. [#67103](https://github.com/ClickHouse/ClickHouse/pull/67103) ([李扬](https://github.com/taiyang-li)).
* Read configuration for `clickhouse-local` from `~/.clickhouse-local`. [#67135](https://github.com/ClickHouse/ClickHouse/pull/67135) ([Azat Khuzhin](https://github.com/azat)).
* Rename setting `input_format_orc_read_use_writer_time_zone` to `input_format_orc_reader_timezone` and allow the user to set the reader timezone. [#67175](https://github.com/ClickHouse/ClickHouse/pull/67175) ([kevinyhzou](https://github.com/KevinyhZou)).
* Decrease level of the `Socket is not connected` error when HTTP connection immediately reset by peer after connecting, close [#34218](https://github.com/ClickHouse/ClickHouse/issues/34218). [#67177](https://github.com/ClickHouse/ClickHouse/pull/67177) ([vdimir](https://github.com/vdimir)).
* Add ability to load dashboards for `system.dashboards` from config (once set, they overrides the default dashboards preset). [#67232](https://github.com/ClickHouse/ClickHouse/pull/67232) ([Azat Khuzhin](https://github.com/azat)).
* The window functions in SQL are traditionally in snake case. ClickHouse uses `camelCase`, so new aliases `denseRank()` and `percentRank()` have been created. These new functions can be called the exact same as the original `dense_rank()` and `percent_rank()` functions. Both snake case and camelCase syntaxes remain usable. A new test for each of the functions has been added as well. This closes [#67042](https://github.com/ClickHouse/ClickHouse/issues/67042) . [#67334](https://github.com/ClickHouse/ClickHouse/pull/67334) ([Peter Nguyen](https://github.com/petern48)).
* Autodetect configuration file format if is not `.xml`, `.yml` or `.yaml`. If the file begins with &lt; it might be XML, otherwise it might be YAML. It is useful when providing a configuration file from a pipe: `clickhouse-server --config-file <(echo "hello: world")`. [#67391](https://github.com/ClickHouse/ClickHouse/pull/67391) ([sakulali](https://github.com/sakulali)).
* Functions `formatDateTime` and `formatDateTimeInJodaSyntax` now treat their format parameter as optional. If it is not specified, format strings `%Y-%m-%d %H:%i:%s` and `yyyy-MM-dd HH:mm:ss` are assumed. Example: `SELECT parseDateTime('2021-01-04 23:12:34')` now returns DateTime value `2021-01-04 23:12:34` (previously, this threw an exception). [#67399](https://github.com/ClickHouse/ClickHouse/pull/67399) ([Robert Schulze](https://github.com/rschu1ze)).
* Automatically retry Keeper requests in KeeperMap if they happen because of timeout or connection loss. [#67448](https://github.com/ClickHouse/ClickHouse/pull/67448) ([Antonio Andelic](https://github.com/antonio2368)).
* Add `-no-pie` to Aarch64 Linux builds to allow proper introspection and symbolizing of stacktraces after a ClickHouse restart. [#67916](https://github.com/ClickHouse/ClickHouse/pull/67916) ([filimonov](https://github.com/filimonov)).
* Added profile events for merges and mutations for better introspection. [#68015](https://github.com/ClickHouse/ClickHouse/pull/68015) ([Anton Popov](https://github.com/CurtizJ)).
* Fix settings and `current_database` in `system.processes` for async BACKUP/RESTORE. [#68163](https://github.com/ClickHouse/ClickHouse/pull/68163) ([Azat Khuzhin](https://github.com/azat)).
* Remove unnecessary logs for non-replicated `MergeTree`. [#68238](https://github.com/ClickHouse/ClickHouse/pull/68238) ([Daniil Ivanik](https://github.com/divanik)).
#### Build/Testing/Packaging Improvement
* Integration tests flaky check will not run each test case multiple times to find more issues in tests and make them more reliable. It is using `pytest-repeat` library to run test case multiple times for the same environment. It is important to cleanup tables and other entities in the end of a test case to pass. Repeating works much faster than several pytest runs as it starts necessary containers only once. [#66986](https://github.com/ClickHouse/ClickHouse/pull/66986) ([Ilya Yatsishin](https://github.com/qoega)).
* Unblock the usage of CLion with ClickHouse. In previous versions, CLion freezed for a minute on every keypress. This closes [#66994](https://github.com/ClickHouse/ClickHouse/issues/66994). [#66995](https://github.com/ClickHouse/ClickHouse/pull/66995) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* getauxval: avoid a crash under a sanitizer re-exec due to high ASLR entropy in newer Linux kernels. [#67081](https://github.com/ClickHouse/ClickHouse/pull/67081) ([Raúl Marín](https://github.com/Algunenano)).
* Some parts of client code are extracted to a single file and highest possible level optimization is applied to them even for debug builds. This closes: [#65745](https://github.com/ClickHouse/ClickHouse/issues/65745). [#67215](https://github.com/ClickHouse/ClickHouse/pull/67215) ([Nikita Mikhaylov](https://github.com/nikitamikhaylov)).
#### Bug Fix
* Only relevant to the experimental Variant data type. Fix crash with Variant + AggregateFunction type. [#67122](https://github.com/ClickHouse/ClickHouse/pull/67122) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix crash in DistributedAsyncInsert when connection is empty. [#67219](https://github.com/ClickHouse/ClickHouse/pull/67219) ([Pablo Marcos](https://github.com/pamarcos)).
* Fix crash of `uniq` and `uniqTheta ` with `tuple()` argument. Closes [#67303](https://github.com/ClickHouse/ClickHouse/issues/67303). [#67306](https://github.com/ClickHouse/ClickHouse/pull/67306) ([flynn](https://github.com/ucasfl)).
* Fixes [#66026](https://github.com/ClickHouse/ClickHouse/issues/66026). Avoid unresolved table function arguments traversal in `ReplaceTableNodeToDummyVisitor`. [#67522](https://github.com/ClickHouse/ClickHouse/pull/67522) ([Dmitry Novik](https://github.com/novikd)).
* Fix potential stack overflow in `JSONMergePatch` function. Renamed this function from `jsonMergePatch` to `JSONMergePatch` because the previous name was wrong. The previous name is still kept for compatibility. Improved diagnostic of errors in the function. This closes [#67304](https://github.com/ClickHouse/ClickHouse/issues/67304). [#67756](https://github.com/ClickHouse/ClickHouse/pull/67756) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Fixed a NULL pointer dereference, triggered by a specially crafted query, that crashed the server via hopEnd, hopStart, tumbleEnd, and tumbleStart. [#68098](https://github.com/ClickHouse/ClickHouse/pull/68098) ([Salvatore Mesoraca](https://github.com/aiven-sal)).
* Fixed `Not-ready Set` in some system tables when filtering using subqueries. [#66018](https://github.com/ClickHouse/ClickHouse/pull/66018) ([Michael Kolupaev](https://github.com/al13n321)).
* Fixed reading of subcolumns after `ALTER ADD COLUMN` query. [#66243](https://github.com/ClickHouse/ClickHouse/pull/66243) ([Anton Popov](https://github.com/CurtizJ)).
* Fix boolean literals in query sent to external database (for engines like `PostgreSQL`). [#66282](https://github.com/ClickHouse/ClickHouse/pull/66282) ([vdimir](https://github.com/vdimir)).
* Fix formatting of query with aliased JOIN ON expression, e.g. `... JOIN t2 ON (x = y) AS e ORDER BY x` should be formatted as `... JOIN t2 ON ((x = y) AS e) ORDER BY x`. [#66312](https://github.com/ClickHouse/ClickHouse/pull/66312) ([vdimir](https://github.com/vdimir)).
* Fix cluster() for inter-server secret (preserve initial user as before). [#66364](https://github.com/ClickHouse/ClickHouse/pull/66364) ([Azat Khuzhin](https://github.com/azat)).
* Fix possible runtime error while converting Array field with nulls to Array(Variant). [#66727](https://github.com/ClickHouse/ClickHouse/pull/66727) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix for occasional deadlock in Context::getDDLWorker. [#66843](https://github.com/ClickHouse/ClickHouse/pull/66843) ([Alexander Gololobov](https://github.com/davenger)).
* Fix creating KeeperMap table after an incomplete drop. [#66865](https://github.com/ClickHouse/ClickHouse/pull/66865) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix broken part error while restoring to a `s3_plain_rewritable` disk. [#66881](https://github.com/ClickHouse/ClickHouse/pull/66881) ([Vitaly Baranov](https://github.com/vitlibar)).
* In rare cases ClickHouse could consider parts as broken because of some unexpected projections on disk. Now it's fixed. [#66898](https://github.com/ClickHouse/ClickHouse/pull/66898) ([alesapin](https://github.com/alesapin)).
* Fix invalid format detection in schema inference that could lead to logical error Format {} doesn't support schema inference. [#66899](https://github.com/ClickHouse/ClickHouse/pull/66899) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix possible deadlock on query cancel with parallel replicas. [#66905](https://github.com/ClickHouse/ClickHouse/pull/66905) ([Nikita Taranov](https://github.com/nickitat)).
* Forbid create as select even when database_replicated_allow_heavy_create is set. It was unconditionally forbidden in 23.12 and accidentally allowed under the setting in unreleased 24.7. [#66980](https://github.com/ClickHouse/ClickHouse/pull/66980) ([vdimir](https://github.com/vdimir)).
* Reading from the `numbers` could wrongly throw an exception when the `max_rows_to_read` limit was set. This closes [#66992](https://github.com/ClickHouse/ClickHouse/issues/66992). [#66996](https://github.com/ClickHouse/ClickHouse/pull/66996) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Add proper type conversion to lagInFrame and leadInFrame window functions - fixes msan test. [#67091](https://github.com/ClickHouse/ClickHouse/pull/67091) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)).
* TRUNCATE DATABASE used to stop replication as if it was a DROP DATABASE query, it's fixed. [#67129](https://github.com/ClickHouse/ClickHouse/pull/67129) ([Alexander Tokmakov](https://github.com/tavplubix)).
* Use a separate client context in `clickhouse-local`. [#67133](https://github.com/ClickHouse/ClickHouse/pull/67133) ([Vitaly Baranov](https://github.com/vitlibar)).
* Fix error `Cannot convert column because it is non constant in source stream but must be constant in result.` for a query that reads from the `Merge` table over the `Distriburted` table with one shard. [#67146](https://github.com/ClickHouse/ClickHouse/pull/67146) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Correct behavior of `ORDER BY all` with disabled `enable_order_by_all` and parallel replicas (distributed queries as well). [#67153](https://github.com/ClickHouse/ClickHouse/pull/67153) ([Igor Nikonov](https://github.com/devcrafter)).
* Fix wrong usage of input_format_max_bytes_to_read_for_schema_inference in schema cache. [#67157](https://github.com/ClickHouse/ClickHouse/pull/67157) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix the memory leak for count distinct, when exception issued during group by single nullable key. [#67171](https://github.com/ClickHouse/ClickHouse/pull/67171) ([Jet He](https://github.com/compasses)).
* Fix an error in optimization which converts OUTER JOIN to INNER JOIN. This closes [#67156](https://github.com/ClickHouse/ClickHouse/issues/67156). This closes [#66447](https://github.com/ClickHouse/ClickHouse/issues/66447). The bug was introduced in https://github.com/ClickHouse/ClickHouse/pull/62907. [#67178](https://github.com/ClickHouse/ClickHouse/pull/67178) ([Maksim Kita](https://github.com/kitaisreal)).
* Fix error `Conversion from AggregateFunction(name, Type) to AggregateFunction(name, Nullable(Type)) is not supported`. The bug was caused by the `optimize_rewrite_aggregate_function_with_if` optimization. Fixes [#67112](https://github.com/ClickHouse/ClickHouse/issues/67112). [#67229](https://github.com/ClickHouse/ClickHouse/pull/67229) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Fix hung query when using empty tuple as lhs of function IN. [#67295](https://github.com/ClickHouse/ClickHouse/pull/67295) ([Duc Canh Le](https://github.com/canhld94)).
* It was possible to create a very deep nested JSON data that triggered stack overflow while skipping unknown fields. This closes [#67292](https://github.com/ClickHouse/ClickHouse/issues/67292). [#67324](https://github.com/ClickHouse/ClickHouse/pull/67324) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Fix attaching ReplicatedMergeTree table after exception during startup. [#67360](https://github.com/ClickHouse/ClickHouse/pull/67360) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix segfault caused by incorrectly detaching from thread group in `Aggregator`. [#67385](https://github.com/ClickHouse/ClickHouse/pull/67385) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix one more case when a non-deterministic function is specified in PK. [#67395](https://github.com/ClickHouse/ClickHouse/pull/67395) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Fixed `bloom_filter` index breaking queries with mildly weird conditions like `(k=2)=(k=2)` or `has([1,2,3], k)`. [#67423](https://github.com/ClickHouse/ClickHouse/pull/67423) ([Michael Kolupaev](https://github.com/al13n321)).
* Correctly parse file name/URI containing `::` if it's not an archive. [#67433](https://github.com/ClickHouse/ClickHouse/pull/67433) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix wait for tasks in ~WriteBufferFromS3 in case WriteBuffer was cancelled. [#67459](https://github.com/ClickHouse/ClickHouse/pull/67459) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Protect temporary part directories from removing during RESTORE. [#67491](https://github.com/ClickHouse/ClickHouse/pull/67491) ([Vitaly Baranov](https://github.com/vitlibar)).
* Fix execution of nested short-circuit functions. [#67520](https://github.com/ClickHouse/ClickHouse/pull/67520) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix `Logical error: Expected the argument №N of type T to have X rows, but it has 0`. The error could happen in a remote query with constant expression in `GROUP BY` (with a new analyzer). [#67536](https://github.com/ClickHouse/ClickHouse/pull/67536) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Fix join on tuple with NULLs: Some queries with the new analyzer and `NULL` inside the tuple in the `JOIN ON` section returned incorrect results. [#67538](https://github.com/ClickHouse/ClickHouse/pull/67538) ([vdimir](https://github.com/vdimir)).
* Fix redundant reschedule of FileCache::freeSpaceRatioKeepingThreadFunc() in case of full non-evictable cache. [#67540](https://github.com/ClickHouse/ClickHouse/pull/67540) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Fix inserting into stream like engines (Kafka, RabbitMQ, NATS) through HTTP interface. [#67554](https://github.com/ClickHouse/ClickHouse/pull/67554) ([János Benjamin Antal](https://github.com/antaljanosbenjamin)).
* Fix for function `toStartOfWeek` which returned the wrong result with a small `DateTime64` value. [#67558](https://github.com/ClickHouse/ClickHouse/pull/67558) ([Yarik Briukhovetskyi](https://github.com/yariks5s)).
* Fix creation of view with recursive CTE. [#67587](https://github.com/ClickHouse/ClickHouse/pull/67587) ([Yakov Olkhovskiy](https://github.com/yakov-olkhovskiy)).
* Fix `Logical error: 'file_offset_of_buffer_end <= read_until_position'` in filesystem cache. Closes [#57508](https://github.com/ClickHouse/ClickHouse/issues/57508). [#67623](https://github.com/ClickHouse/ClickHouse/pull/67623) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Fixes [#62282](https://github.com/ClickHouse/ClickHouse/issues/62282). Removed the call to `convertFieldToString()` and added datatype specific serialization code. Parameterized view substitution was broken for multiple datatypes when parameter value was a function or expression returning datatype instance. [#67654](https://github.com/ClickHouse/ClickHouse/pull/67654) ([Shankar](https://github.com/shiyer7474)).
* Fix crash on `percent_rank`. `percent_rank`'s default frame type is changed to `range unbounded preceding and unbounded following`. `IWindowFunction`'s default window frame is considered and now window functions without window frame definition in sql can be put into different `WindowTransfomer`s properly. [#67661](https://github.com/ClickHouse/ClickHouse/pull/67661) ([lgbo](https://github.com/lgbo-ustc)).
* Fix reloading SQL UDFs with UNION. Previously, restarting the server could make UDF invalid. [#67665](https://github.com/ClickHouse/ClickHouse/pull/67665) ([Antonio Andelic](https://github.com/antonio2368)).
* Fix possible logical error "Unexpected return type from if" with experimental Variant type and enabled setting `use_variant_as_common_type ` in function if with Tuples and Maps. [#67687](https://github.com/ClickHouse/ClickHouse/pull/67687) ([Kruglov Pavel](https://github.com/Avogar)).
* Due to a bug in Linux Kernel, a query can hung in `TimerDescriptor::drain`. This closes [#37686](https://github.com/ClickHouse/ClickHouse/issues/37686). [#67702](https://github.com/ClickHouse/ClickHouse/pull/67702) ([Alexey Milovidov](https://github.com/alexey-milovidov)).
* Fix completion of `RESTORE ON CLUSTER` command. [#67720](https://github.com/ClickHouse/ClickHouse/pull/67720) ([Vitaly Baranov](https://github.com/vitlibar)).
* Fix dictionary hang in case of CANNOT_SCHEDULE_TASK while loading. [#67751](https://github.com/ClickHouse/ClickHouse/pull/67751) ([Azat Khuzhin](https://github.com/azat)).
* Queries like `SELECT count() FROM t WHERE cast(c = 1 or c = 9999 AS Bool) SETTINGS use_skip_indexes=1` with bloom filter indexes on `c` now work correctly. [#67781](https://github.com/ClickHouse/ClickHouse/pull/67781) ([jsc0218](https://github.com/jsc0218)).
* Fix wrong aggregation result in some queries with aggregation without keys and filter, close [#67419](https://github.com/ClickHouse/ClickHouse/issues/67419). [#67804](https://github.com/ClickHouse/ClickHouse/pull/67804) ([vdimir](https://github.com/vdimir)).
* Validate experimental/suspicious data types in ALTER ADD/MODIFY COLUMN. [#67911](https://github.com/ClickHouse/ClickHouse/pull/67911) ([Kruglov Pavel](https://github.com/Avogar)).
* Fix DateTime64 parsing after constant folding in distributed queries, close [#66773](https://github.com/ClickHouse/ClickHouse/issues/66773). [#67920](https://github.com/ClickHouse/ClickHouse/pull/67920) ([vdimir](https://github.com/vdimir)).
* Fix wrong `count()` result when there is non-deterministic function in predicate. [#67922](https://github.com/ClickHouse/ClickHouse/pull/67922) ([János Benjamin Antal](https://github.com/antaljanosbenjamin)).
* Fixed the calculation of the maximum thread soft limit in containerized environments where the usable CPU count is limited. [#67963](https://github.com/ClickHouse/ClickHouse/pull/67963) ([Robert Schulze](https://github.com/rschu1ze)).
* Now ClickHouse doesn't consider part as broken if projection doesn't exist on disk but exists in `checksums.txt`. [#68003](https://github.com/ClickHouse/ClickHouse/pull/68003) ([alesapin](https://github.com/alesapin)).
* Fixed skipping of untouched parts in mutations with new analyzer. Previously with enabled analyzer data in part could be rewritten by mutation even if mutation doesn't affect this part according to predicate. [#68052](https://github.com/ClickHouse/ClickHouse/pull/68052) ([Anton Popov](https://github.com/CurtizJ)).
* Removes an incorrect optimization to remove sorting in subqueries that use `OFFSET`. Fixes [#67906](https://github.com/ClickHouse/ClickHouse/issues/67906). [#68099](https://github.com/ClickHouse/ClickHouse/pull/68099) ([Graham Campbell](https://github.com/GrahamCampbell)).
* Attempt to fix `Block structure mismatch in AggregatingStep stream: different types` for aggregate projection optimization. [#68107](https://github.com/ClickHouse/ClickHouse/pull/68107) ([Nikolai Kochetov](https://github.com/KochetovNicolai)).
* Try fix postgres crash when query is cancelled. [#68288](https://github.com/ClickHouse/ClickHouse/pull/68288) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Fix missing sync replica mode in query `SYSTEM SYNC REPLICA`. [#68326](https://github.com/ClickHouse/ClickHouse/pull/68326) ([Duc Canh Le](https://github.com/canhld94)).
### <a id="247"></a> ClickHouse release 24.7, 2024-07-30 ### <a id="247"></a> ClickHouse release 24.7, 2024-07-30
#### Backward Incompatible Change #### Backward Incompatible Change

View File

@ -605,7 +605,9 @@ if (NATIVE_BUILD_TARGETS
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} -E make_directory "${NATIVE_BUILD_DIR}" COMMAND ${CMAKE_COMMAND} -E make_directory "${NATIVE_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
@ -617,9 +619,13 @@ if (NATIVE_BUILD_TARGETS
"-DENABLE_CLICKHOUSE_SELF_EXTRACTING=${ENABLE_CLICKHOUSE_SELF_EXTRACTING}" "-DENABLE_CLICKHOUSE_SELF_EXTRACTING=${ENABLE_CLICKHOUSE_SELF_EXTRACTING}"
${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}
WORKING_DIRECTORY "${NATIVE_BUILD_DIR}" WORKING_DIRECTORY "${NATIVE_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} --build "${NATIVE_BUILD_DIR}" --target ${NATIVE_BUILD_TARGETS} COMMAND ${CMAKE_COMMAND} --build "${NATIVE_BUILD_DIR}" --target ${NATIVE_BUILD_TARGETS}
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
endif () endif ()

View File

@ -51,8 +51,14 @@ if (NOT "$ENV{CFLAGS}" STREQUAL ""
endif() endif()
# Default toolchain - this is needed to avoid dependency on OS files. # Default toolchain - this is needed to avoid dependency on OS files.
execute_process(COMMAND uname -s OUTPUT_VARIABLE OS) execute_process(COMMAND uname -s
execute_process(COMMAND uname -m OUTPUT_VARIABLE ARCH) OUTPUT_VARIABLE OS
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(COMMAND uname -m
OUTPUT_VARIABLE ARCH
COMMAND_ERROR_IS_FATAL ANY
)
# By default, prefer clang on Linux # By default, prefer clang on Linux
# But note, that you still may change the compiler with -DCMAKE_C_COMPILER/-DCMAKE_CXX_COMPILER. # But note, that you still may change the compiler with -DCMAKE_C_COMPILER/-DCMAKE_CXX_COMPILER.

View File

@ -8,6 +8,8 @@ endif ()
# when instantiated from JSON.cpp. Try again when libcxx(abi) and Clang are upgraded to 16. # when instantiated from JSON.cpp. Try again when libcxx(abi) and Clang are upgraded to 16.
set (CMAKE_CXX_STANDARD 20) set (CMAKE_CXX_STANDARD 20)
configure_file(GitHash.cpp.in GitHash.generated.cpp)
set (SRCS set (SRCS
argsToConfig.cpp argsToConfig.cpp
cgroupsv2.cpp cgroupsv2.cpp
@ -33,6 +35,7 @@ set (SRCS
safeExit.cpp safeExit.cpp
throwError.cpp throwError.cpp
Numa.cpp Numa.cpp
GitHash.generated.cpp
) )
add_library (common ${SRCS}) add_library (common ${SRCS})

View File

@ -9,10 +9,18 @@ endif ()
file(GLOB bprefix "/usr/local/llvm${COMPILER_VERSION_MAJOR}/lib/clang/${COMPILER_VERSION_MAJOR}/lib/${system_processor}-portbld-freebsd*/") file(GLOB bprefix "/usr/local/llvm${COMPILER_VERSION_MAJOR}/lib/clang/${COMPILER_VERSION_MAJOR}/lib/${system_processor}-portbld-freebsd*/")
message(STATUS "-Bprefix: ${bprefix}") message(STATUS "-Bprefix: ${bprefix}")
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -Bprefix=${bprefix} --print-file-name=libclang_rt.builtins-${system_processor}.a OUTPUT_VARIABLE BUILTINS_LIBRARY OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND
${CMAKE_CXX_COMPILER} -Bprefix=${bprefix} --print-file-name=libclang_rt.builtins-${system_processor}.a
OUTPUT_VARIABLE BUILTINS_LIBRARY
COMMAND_ERROR_IS_FATAL ANY
OUTPUT_STRIP_TRAILING_WHITESPACE)
# --print-file-name simply prints what you passed in case of nothing was resolved, so let's try one other possible option # --print-file-name simply prints what you passed in case of nothing was resolved, so let's try one other possible option
if (BUILTINS_LIBRARY STREQUAL "libclang_rt.builtins-${system_processor}.a") if (BUILTINS_LIBRARY STREQUAL "libclang_rt.builtins-${system_processor}.a")
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -Bprefix=${bprefix} --print-file-name=libclang_rt.builtins.a OUTPUT_VARIABLE BUILTINS_LIBRARY OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND
${CMAKE_CXX_COMPILER} -Bprefix=${bprefix} --print-file-name=libclang_rt.builtins.a
OUTPUT_VARIABLE BUILTINS_LIBRARY
COMMAND_ERROR_IS_FATAL ANY
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif() endif()
if (BUILTINS_LIBRARY STREQUAL "libclang_rt.builtins.a") if (BUILTINS_LIBRARY STREQUAL "libclang_rt.builtins.a")
message(FATAL_ERROR "libclang_rt.builtins had not been found") message(FATAL_ERROR "libclang_rt.builtins had not been found")

View File

@ -42,19 +42,9 @@ endif ()
# But use 2 parallel jobs, since: # But use 2 parallel jobs, since:
# - this is what llvm does # - this is what llvm does
# - and I've verfied that lld-11 does not use all available CPU time (in peak) while linking one binary # - and I've verfied that lld-11 does not use all available CPU time (in peak) while linking one binary
if (CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO" AND ENABLE_THINLTO) if (CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO" AND ENABLE_THINLTO AND PARALLEL_LINK_JOBS GREATER 2)
if (ARCH_AARCH64) message(STATUS "ThinLTO provides its own parallel linking - limiting parallel link jobs to 2.")
# aarch64 builds start to often fail with OOMs (reason not yet clear), for now let's limit the concurrency set (PARALLEL_LINK_JOBS 2)
message(STATUS "ThinLTO provides its own parallel linking - limiting parallel link jobs to 1.")
set (PARALLEL_LINK_JOBS 1)
if (LINKER_NAME MATCHES "lld")
math(EXPR LTO_JOBS ${NUMBER_OF_LOGICAL_CORES}/4)
set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -Wl,--thinlto-jobs=${LTO_JOBS}")
endif()
elseif (PARALLEL_LINK_JOBS GREATER 2)
message(STATUS "ThinLTO provides its own parallel linking - limiting parallel link jobs to 2.")
set (PARALLEL_LINK_JOBS 2)
endif ()
endif() endif()
message(STATUS "Building sub-tree with ${PARALLEL_COMPILE_JOBS} compile jobs and ${PARALLEL_LINK_JOBS} linker jobs (system: ${NUMBER_OF_LOGICAL_CORES} cores, ${TOTAL_PHYSICAL_MEMORY} MB RAM, 'OFF' means the native core count).") message(STATUS "Building sub-tree with ${PARALLEL_COMPILE_JOBS} compile jobs and ${PARALLEL_LINK_JOBS} linker jobs (system: ${NUMBER_OF_LOGICAL_CORES} cores, ${TOTAL_PHYSICAL_MEMORY} MB RAM, 'OFF' means the native core count).")

View File

@ -5,7 +5,11 @@ set (DEFAULT_LIBS "-nodefaultlibs")
# We need builtins from Clang's RT even without libcxx - for ubsan+int128. # We need builtins from Clang's RT even without libcxx - for ubsan+int128.
# See https://bugs.llvm.org/show_bug.cgi?id=16404 # See https://bugs.llvm.org/show_bug.cgi?id=16404
execute_process (COMMAND ${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET} --print-libgcc-file-name --rtlib=compiler-rt OUTPUT_VARIABLE BUILTINS_LIBRARY OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND
${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET} --print-libgcc-file-name --rtlib=compiler-rt
OUTPUT_VARIABLE BUILTINS_LIBRARY
COMMAND_ERROR_IS_FATAL ANY
OUTPUT_STRIP_TRAILING_WHITESPACE)
# Apparently, in clang-19, the UBSan support library for C++ was moved out into ubsan_standalone_cxx.a, so we have to include both. # Apparently, in clang-19, the UBSan support library for C++ was moved out into ubsan_standalone_cxx.a, so we have to include both.
if (SANITIZE STREQUAL undefined) if (SANITIZE STREQUAL undefined)

View File

@ -5,7 +5,11 @@ if (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
endif () endif ()
# Print details to output # Print details to output
execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE COMPILER_SELF_IDENTIFICATION OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
OUTPUT_VARIABLE COMPILER_SELF_IDENTIFICATION
COMMAND_ERROR_IS_FATAL ANY
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message (STATUS "Using compiler:\n${COMPILER_SELF_IDENTIFICATION}") message (STATUS "Using compiler:\n${COMPILER_SELF_IDENTIFICATION}")
# Require minimum compiler versions # Require minimum compiler versions

View File

@ -90,7 +90,10 @@ endfunction()
# Function get_cmake_properties returns list of all propreties that cmake supports # Function get_cmake_properties returns list of all propreties that cmake supports
function(get_cmake_properties outvar) function(get_cmake_properties outvar)
execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE cmake_properties) execute_process(COMMAND cmake --help-property-list
OUTPUT_VARIABLE cmake_properties
COMMAND_ERROR_IS_FATAL ANY
)
# Convert command output into a CMake list # Convert command output into a CMake list
string(REGEX REPLACE ";" "\\\\;" cmake_properties "${cmake_properties}") string(REGEX REPLACE ";" "\\\\;" cmake_properties "${cmake_properties}")
string(REGEX REPLACE "\n" ";" cmake_properties "${cmake_properties}") string(REGEX REPLACE "\n" ";" cmake_properties "${cmake_properties}")

2
contrib/aws vendored

@ -1 +1 @@
Subproject commit 1c2946bfcb7f1e3ae0a858de0b59d4f1a7b4ccaf Subproject commit d5450d76abda556ce145ddabe7e0cc6a7644ec59

2
contrib/aws-crt-cpp vendored

@ -1 +1 @@
Subproject commit f532d6abc0d2b0d8b5d6fe9e7c51eaedbe4afbd0 Subproject commit e5aa45cacfdcda7719ead38760e7c61076f5745f

View File

@ -37,7 +37,9 @@ message(STATUS "Packaging with tzdata version: ${TZDATA_VERSION}")
execute_process(COMMAND execute_process(COMMAND
bash -c "cd ${TZDIR} && find * -type f -and ! -name '*.tab' -and ! -name 'localtime' | LC_ALL=C sort | paste -sd ';' -" bash -c "cd ${TZDIR} && find * -type f -and ! -name '*.tab' -and ! -name 'localtime' | LC_ALL=C sort | paste -sd ';' -"
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE TIMEZONES) OUTPUT_VARIABLE TIMEZONES
COMMAND_ERROR_IS_FATAL ANY
)
file(APPEND ${TIMEZONES_FILE} "// autogenerated by ClickHouse/contrib/cctz-cmake/CMakeLists.txt\n") file(APPEND ${TIMEZONES_FILE} "// autogenerated by ClickHouse/contrib/cctz-cmake/CMakeLists.txt\n")
file(APPEND ${TIMEZONES_FILE} "#include <incbin.h>\n") file(APPEND ${TIMEZONES_FILE} "#include <incbin.h>\n")

View File

@ -359,7 +359,9 @@ else ()
execute_process( execute_process(
COMMAND mkdir -p ${PROTOC_BUILD_DIR} COMMAND mkdir -p ${PROTOC_BUILD_DIR}
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
@ -375,11 +377,15 @@ else ()
"-DABSL_ENABLE_INSTALL=0" "-DABSL_ENABLE_INSTALL=0"
"${protobuf_source_dir}" "${protobuf_source_dir}"
WORKING_DIRECTORY "${PROTOC_BUILD_DIR}" WORKING_DIRECTORY "${PROTOC_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} --build "${PROTOC_BUILD_DIR}" COMMAND ${CMAKE_COMMAND} --build "${PROTOC_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
endif () endif ()
add_executable(protoc IMPORTED GLOBAL) add_executable(protoc IMPORTED GLOBAL)

View File

@ -51,8 +51,9 @@ if (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME
set(OPENSSL_SOURCE_DIR "${ClickHouse_SOURCE_DIR}/contrib/openssl-cmake") set(OPENSSL_SOURCE_DIR "${ClickHouse_SOURCE_DIR}/contrib/openssl-cmake")
execute_process( execute_process(
COMMAND mkdir -p ${OPENSSL_BUILD_DIR} COMMAND mkdir -p ${OPENSSL_BUILD_DIR}
COMMAND_ECHO STDOUT COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
) )
if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64") if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64")
@ -89,15 +90,21 @@ if (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME
"-DClickHouse_SOURCE_DIR=${ClickHouse_SOURCE_DIR}" "-DClickHouse_SOURCE_DIR=${ClickHouse_SOURCE_DIR}"
"${OPENSSL_SOURCE_DIR}" "${OPENSSL_SOURCE_DIR}"
WORKING_DIRECTORY "${OPENSSL_BUILD_DIR}" WORKING_DIRECTORY "${OPENSSL_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} --build "${OPENSSL_BUILD_DIR}" COMMAND ${CMAKE_COMMAND} --build "${OPENSSL_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} --install "${OPENSSL_BUILD_DIR}" COMMAND ${CMAKE_COMMAND} --install "${OPENSSL_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
# It's not important on which file we depend, we just want to specify right order # It's not important on which file we depend, we just want to specify right order
add_library(openssl_for_grpc STATIC IMPORTED GLOBAL) add_library(openssl_for_grpc STATIC IMPORTED GLOBAL)
@ -108,8 +115,9 @@ if (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME
set (GRPC_CPP_PLUGIN_BUILD_DIR "${_gRPC_BINARY_DIR}/build") set (GRPC_CPP_PLUGIN_BUILD_DIR "${_gRPC_BINARY_DIR}/build")
execute_process( execute_process(
COMMAND mkdir -p ${GRPC_CPP_PLUGIN_BUILD_DIR} COMMAND mkdir -p ${GRPC_CPP_PLUGIN_BUILD_DIR}
COMMAND_ECHO STDOUT COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
) )
set(abseil_source_dir "${ClickHouse_SOURCE_DIR}/contrib/abseil-cpp") set(abseil_source_dir "${ClickHouse_SOURCE_DIR}/contrib/abseil-cpp")
@ -140,11 +148,15 @@ if (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME
"-DgRPC_SSL_PROVIDER=package" "-DgRPC_SSL_PROVIDER=package"
"${_gRPC_SOURCE_DIR}" "${_gRPC_SOURCE_DIR}"
WORKING_DIRECTORY "${GRPC_CPP_PLUGIN_BUILD_DIR}" WORKING_DIRECTORY "${GRPC_CPP_PLUGIN_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process( execute_process(
COMMAND ${CMAKE_COMMAND} --build "${GRPC_CPP_PLUGIN_BUILD_DIR}" COMMAND ${CMAKE_COMMAND} --build "${GRPC_CPP_PLUGIN_BUILD_DIR}"
COMMAND_ECHO STDOUT) COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
add_executable(grpc_cpp_plugin IMPORTED GLOBAL) add_executable(grpc_cpp_plugin IMPORTED GLOBAL)
set_target_properties (grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION "${GRPC_CPP_PLUGIN_BUILD_DIR}/grpc_cpp_plugin") set_target_properties (grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION "${GRPC_CPP_PLUGIN_BUILD_DIR}/grpc_cpp_plugin")

2
contrib/icu vendored

@ -1 +1 @@
Subproject commit 7750081bda4b3bc1768ae03849ec70f67ea10625 Subproject commit 4216173eeeb39c1d4caaa54a68860e800412d273

View File

@ -256,22 +256,6 @@ function configure
rm -f "$FASTTEST_DATA/config.d/secure_ports.xml" rm -f "$FASTTEST_DATA/config.d/secure_ports.xml"
} }
function timeout_with_logging() {
local exit_code=0
timeout -s TERM --preserve-status "${@}" || exit_code="${?}"
echo "Checking if it is a timeout. The code 124 will indicate a timeout."
if [[ "${exit_code}" -eq "124" ]]
then
echo "The command 'timeout ${*}' has been killed by timeout."
else
echo "No, it isn't a timeout."
fi
return $exit_code
}
function run_tests function run_tests
{ {
clickhouse-server --version clickhouse-server --version
@ -340,7 +324,7 @@ case "$stage" in
configure 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee "$FASTTEST_OUTPUT/install_log.txt" configure 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee "$FASTTEST_OUTPUT/install_log.txt"
;& ;&
"run_tests") "run_tests")
timeout_with_logging 35m bash -c run_tests ||: run_tests ||:
/process_functional_tests_result.py --in-results-dir "$FASTTEST_OUTPUT/" \ /process_functional_tests_result.py --in-results-dir "$FASTTEST_OUTPUT/" \
--out-results-file "$FASTTEST_OUTPUT/test_results.tsv" \ --out-results-file "$FASTTEST_OUTPUT/test_results.tsv" \
--out-status-file "$FASTTEST_OUTPUT/check_status.tsv" || echo -e "failure\tCannot parse results" > "$FASTTEST_OUTPUT/check_status.tsv" --out-status-file "$FASTTEST_OUTPUT/check_status.tsv" || echo -e "failure\tCannot parse results" > "$FASTTEST_OUTPUT/check_status.tsv"

View File

@ -35,7 +35,6 @@ RUN mkdir -p /tmp/clickhouse-odbc-tmp \
ENV TZ=Europe/Amsterdam ENV TZ=Europe/Amsterdam
ENV MAX_RUN_TIME=9000
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ARG sqllogic_test_repo="https://github.com/gregrahn/sqllogictest.git" ARG sqllogic_test_repo="https://github.com/gregrahn/sqllogictest.git"

View File

@ -94,7 +94,7 @@ function run_tests()
export -f run_tests export -f run_tests
timeout "${MAX_RUN_TIME:-9000}" bash -c run_tests || echo "timeout reached" >&2 run_tests
#/process_functional_tests_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv #/process_functional_tests_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv

View File

@ -22,7 +22,6 @@ ARG sqltest_repo="https://github.com/elliotchance/sqltest/"
RUN git clone ${sqltest_repo} RUN git clone ${sqltest_repo}
ENV TZ=UTC ENV TZ=UTC
ENV MAX_RUN_TIME=900
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY run.sh / COPY run.sh /

View File

@ -4,9 +4,6 @@
source /setup_export_logs.sh source /setup_export_logs.sh
set -e -x set -e -x
MAX_RUN_TIME=${MAX_RUN_TIME:-3600}
MAX_RUN_TIME=$((MAX_RUN_TIME == 0 ? 3600 : MAX_RUN_TIME))
# Choose random timezone for this test run # Choose random timezone for this test run
TZ="$(rg -v '#' /usr/share/zoneinfo/zone.tab | awk '{print $3}' | shuf | head -n1)" TZ="$(rg -v '#' /usr/share/zoneinfo/zone.tab | awk '{print $3}' | shuf | head -n1)"
echo "Choosen random timezone $TZ" echo "Choosen random timezone $TZ"
@ -118,14 +115,11 @@ if [[ -n "$USE_DATABASE_REPLICATED" ]] && [[ "$USE_DATABASE_REPLICATED" -eq 1 ]]
clickhouse-client --query "CREATE TABLE test.hits AS datasets.hits_v1" clickhouse-client --query "CREATE TABLE test.hits AS datasets.hits_v1"
clickhouse-client --query "CREATE TABLE test.visits AS datasets.visits_v1" clickhouse-client --query "CREATE TABLE test.visits AS datasets.visits_v1"
clickhouse-client --query "INSERT INTO test.hits SELECT * FROM datasets.hits_v1" clickhouse-client --max_memory_usage 10G --query "INSERT INTO test.hits SELECT * FROM datasets.hits_v1"
clickhouse-client --query "INSERT INTO test.visits SELECT * FROM datasets.visits_v1" clickhouse-client --max_memory_usage 10G --query "INSERT INTO test.visits SELECT * FROM datasets.visits_v1"
clickhouse-client --query "DROP TABLE datasets.hits_v1" clickhouse-client --query "DROP TABLE datasets.hits_v1"
clickhouse-client --query "DROP TABLE datasets.visits_v1" clickhouse-client --query "DROP TABLE datasets.visits_v1"
MAX_RUN_TIME=$((MAX_RUN_TIME < 9000 ? MAX_RUN_TIME : 9000)) # min(MAX_RUN_TIME, 2.5 hours)
MAX_RUN_TIME=$((MAX_RUN_TIME != 0 ? MAX_RUN_TIME : 9000)) # set to 2.5 hours if 0 (unlimited)
else else
clickhouse-client --query "CREATE DATABASE test" clickhouse-client --query "CREATE DATABASE test"
clickhouse-client --query "SHOW TABLES FROM test" clickhouse-client --query "SHOW TABLES FROM test"
@ -191,8 +185,8 @@ else
ENGINE = CollapsingMergeTree(Sign) PARTITION BY toYYYYMM(StartDate) ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID) ENGINE = CollapsingMergeTree(Sign) PARTITION BY toYYYYMM(StartDate) ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)
SAMPLE BY intHash32(UserID) SETTINGS index_granularity = 8192, storage_policy='s3_cache'" SAMPLE BY intHash32(UserID) SETTINGS index_granularity = 8192, storage_policy='s3_cache'"
clickhouse-client --query "INSERT INTO test.hits SELECT * FROM datasets.hits_v1 SETTINGS enable_filesystem_cache_on_write_operations=0, max_insert_threads=16" clickhouse-client --max_memory_usage 10G --query "INSERT INTO test.hits SELECT * FROM datasets.hits_v1 SETTINGS enable_filesystem_cache_on_write_operations=0, max_insert_threads=16"
clickhouse-client --query "INSERT INTO test.visits SELECT * FROM datasets.visits_v1 SETTINGS enable_filesystem_cache_on_write_operations=0, max_insert_threads=16" clickhouse-client --max_memory_usage 10G --query "INSERT INTO test.visits SELECT * FROM datasets.visits_v1 SETTINGS enable_filesystem_cache_on_write_operations=0, max_insert_threads=16"
clickhouse-client --query "DROP TABLE datasets.visits_v1 SYNC" clickhouse-client --query "DROP TABLE datasets.visits_v1 SYNC"
clickhouse-client --query "DROP TABLE datasets.hits_v1 SYNC" clickhouse-client --query "DROP TABLE datasets.hits_v1 SYNC"
else else
@ -200,7 +194,8 @@ else
clickhouse-client --query "RENAME TABLE datasets.visits_v1 TO test.visits" clickhouse-client --query "RENAME TABLE datasets.visits_v1 TO test.visits"
fi fi
clickhouse-client --query "CREATE TABLE test.hits_s3 (WatchID UInt64, JavaEnable UInt8, Title String, GoodEvent Int16, EventTime DateTime, EventDate Date, CounterID UInt32, ClientIP UInt32, ClientIP6 FixedString(16), RegionID UInt32, UserID UInt64, CounterClass Int8, OS UInt8, UserAgent UInt8, URL String, Referer String, URLDomain String, RefererDomain String, Refresh UInt8, IsRobot UInt8, RefererCategories Array(UInt16), URLCategories Array(UInt16), URLRegions Array(UInt32), RefererRegions Array(UInt32), ResolutionWidth UInt16, ResolutionHeight UInt16, ResolutionDepth UInt8, FlashMajor UInt8, FlashMinor UInt8, FlashMinor2 String, NetMajor UInt8, NetMinor UInt8, UserAgentMajor UInt16, UserAgentMinor FixedString(2), CookieEnable UInt8, JavascriptEnable UInt8, IsMobile UInt8, MobilePhone UInt8, MobilePhoneModel String, Params String, IPNetworkID UInt32, TraficSourceID Int8, SearchEngineID UInt16, SearchPhrase String, AdvEngineID UInt8, IsArtifical UInt8, WindowClientWidth UInt16, WindowClientHeight UInt16, ClientTimeZone Int16, ClientEventTime DateTime, SilverlightVersion1 UInt8, SilverlightVersion2 UInt8, SilverlightVersion3 UInt32, SilverlightVersion4 UInt16, PageCharset String, CodeVersion UInt32, IsLink UInt8, IsDownload UInt8, IsNotBounce UInt8, FUniqID UInt64, HID UInt32, IsOldCounter UInt8, IsEvent UInt8, IsParameter UInt8, DontCountHits UInt8, WithHash UInt8, HitColor FixedString(1), UTCEventTime DateTime, Age UInt8, Sex UInt8, Income UInt8, Interests UInt16, Robotness UInt8, GeneralInterests Array(UInt16), RemoteIP UInt32, RemoteIP6 FixedString(16), WindowName Int32, OpenerName Int32, HistoryLength Int16, BrowserLanguage FixedString(2), BrowserCountry FixedString(2), SocialNetwork String, SocialAction String, HTTPError UInt16, SendTiming Int32, DNSTiming Int32, ConnectTiming Int32, ResponseStartTiming Int32, ResponseEndTiming Int32, FetchTiming Int32, RedirectTiming Int32, DOMInteractiveTiming Int32, DOMContentLoadedTiming Int32, DOMCompleteTiming Int32, LoadEventStartTiming Int32, LoadEventEndTiming Int32, NSToDOMContentLoadedTiming Int32, FirstPaintTiming Int32, RedirectCount Int8, SocialSourceNetworkID UInt8, SocialSourcePage String, ParamPrice Int64, ParamOrderID String, ParamCurrency FixedString(3), ParamCurrencyID UInt16, GoalsReached Array(UInt32), OpenstatServiceName String, OpenstatCampaignID String, OpenstatAdID String, OpenstatSourceID String, UTMSource String, UTMMedium String, UTMCampaign String, UTMContent String, UTMTerm String, FromTag String, HasGCLID UInt8, RefererHash UInt64, URLHash UInt64, CLID UInt32, YCLID UInt64, ShareService String, ShareURL String, ShareTitle String, ParsedParams Nested(Key1 String, Key2 String, Key3 String, Key4 String, Key5 String, ValueDouble Float64), IslandID FixedString(16), RequestNum UInt32, RequestTry UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity = 8192, storage_policy='s3_cache'" clickhouse-client --query "CREATE TABLE test.hits_s3 (WatchID UInt64, JavaEnable UInt8, Title String, GoodEvent Int16, EventTime DateTime, EventDate Date, CounterID UInt32, ClientIP UInt32, ClientIP6 FixedString(16), RegionID UInt32, UserID UInt64, CounterClass Int8, OS UInt8, UserAgent UInt8, URL String, Referer String, URLDomain String, RefererDomain String, Refresh UInt8, IsRobot UInt8, RefererCategories Array(UInt16), URLCategories Array(UInt16), URLRegions Array(UInt32), RefererRegions Array(UInt32), ResolutionWidth UInt16, ResolutionHeight UInt16, ResolutionDepth UInt8, FlashMajor UInt8, FlashMinor UInt8, FlashMinor2 String, NetMajor UInt8, NetMinor UInt8, UserAgentMajor UInt16, UserAgentMinor FixedString(2), CookieEnable UInt8, JavascriptEnable UInt8, IsMobile UInt8, MobilePhone UInt8, MobilePhoneModel String, Params String, IPNetworkID UInt32, TraficSourceID Int8, SearchEngineID UInt16, SearchPhrase String, AdvEngineID UInt8, IsArtifical UInt8, WindowClientWidth UInt16, WindowClientHeight UInt16, ClientTimeZone Int16, ClientEventTime DateTime, SilverlightVersion1 UInt8, SilverlightVersion2 UInt8, SilverlightVersion3 UInt32, SilverlightVersion4 UInt16, PageCharset String, CodeVersion UInt32, IsLink UInt8, IsDownload UInt8, IsNotBounce UInt8, FUniqID UInt64, HID UInt32, IsOldCounter UInt8, IsEvent UInt8, IsParameter UInt8, DontCountHits UInt8, WithHash UInt8, HitColor FixedString(1), UTCEventTime DateTime, Age UInt8, Sex UInt8, Income UInt8, Interests UInt16, Robotness UInt8, GeneralInterests Array(UInt16), RemoteIP UInt32, RemoteIP6 FixedString(16), WindowName Int32, OpenerName Int32, HistoryLength Int16, BrowserLanguage FixedString(2), BrowserCountry FixedString(2), SocialNetwork String, SocialAction String, HTTPError UInt16, SendTiming Int32, DNSTiming Int32, ConnectTiming Int32, ResponseStartTiming Int32, ResponseEndTiming Int32, FetchTiming Int32, RedirectTiming Int32, DOMInteractiveTiming Int32, DOMContentLoadedTiming Int32, DOMCompleteTiming Int32, LoadEventStartTiming Int32, LoadEventEndTiming Int32, NSToDOMContentLoadedTiming Int32, FirstPaintTiming Int32, RedirectCount Int8, SocialSourceNetworkID UInt8, SocialSourcePage String, ParamPrice Int64, ParamOrderID String, ParamCurrency FixedString(3), ParamCurrencyID UInt16, GoalsReached Array(UInt32), OpenstatServiceName String, OpenstatCampaignID String, OpenstatAdID String, OpenstatSourceID String, UTMSource String, UTMMedium String, UTMCampaign String, UTMContent String, UTMTerm String, FromTag String, HasGCLID UInt8, RefererHash UInt64, URLHash UInt64, CLID UInt32, YCLID UInt64, ShareService String, ShareURL String, ShareTitle String, ParsedParams Nested(Key1 String, Key2 String, Key3 String, Key4 String, Key5 String, ValueDouble Float64), IslandID FixedString(16), RequestNum UInt32, RequestTry UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity = 8192, storage_policy='s3_cache'"
clickhouse-client --query "INSERT INTO test.hits_s3 SELECT * FROM test.hits SETTINGS enable_filesystem_cache_on_write_operations=0, max_insert_threads=16" # AWS S3 is very inefficient, so increase memory even further:
clickhouse-client --max_memory_usage 30G --max_memory_usage_for_user 30G --query "INSERT INTO test.hits_s3 SELECT * FROM test.hits SETTINGS enable_filesystem_cache_on_write_operations=0, max_insert_threads=16"
fi fi
clickhouse-client --query "SHOW TABLES FROM test" clickhouse-client --query "SHOW TABLES FROM test"
@ -257,24 +252,7 @@ function run_tests()
export -f run_tests export -f run_tests
function timeout_with_logging() { run_tests ||:
local exit_code=0
timeout -s TERM --preserve-status "${@}" || exit_code="${?}"
echo "Checking if it is a timeout. The code 124 will indicate a timeout."
if [[ "${exit_code}" -eq "124" ]]
then
echo "The command 'timeout ${*}' has been killed by timeout."
else
echo "No, it isn't a timeout."
fi
return $exit_code
}
TIMEOUT=$((MAX_RUN_TIME - 700))
timeout_with_logging "$TIMEOUT" bash -c run_tests ||:
echo "Files in current directory" echo "Files in current directory"
ls -la ./ ls -la ./

View File

@ -65,7 +65,6 @@ ENV TZ=Europe/Amsterdam
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENV NUM_TRIES=1 ENV NUM_TRIES=1
ENV MAX_RUN_TIME=0
# Unrelated to vars in setup_minio.sh, but should be the same there # Unrelated to vars in setup_minio.sh, but should be the same there
# to have the same binaries for local running scenario # to have the same binaries for local running scenario

View File

@ -12,9 +12,6 @@ dmesg --clear
# fail on errors, verbose and export all env variables # fail on errors, verbose and export all env variables
set -e -x -a set -e -x -a
MAX_RUN_TIME=${MAX_RUN_TIME:-9000}
MAX_RUN_TIME=$((MAX_RUN_TIME == 0 ? 9000 : MAX_RUN_TIME))
USE_DATABASE_REPLICATED=${USE_DATABASE_REPLICATED:=0} USE_DATABASE_REPLICATED=${USE_DATABASE_REPLICATED:=0}
USE_SHARED_CATALOG=${USE_SHARED_CATALOG:=0} USE_SHARED_CATALOG=${USE_SHARED_CATALOG:=0}
@ -308,8 +305,6 @@ function run_tests()
try_run_with_retry 10 clickhouse-client -q "insert into system.zookeeper (name, path, value) values ('auxiliary_zookeeper2', '/test/chroot/', '')" try_run_with_retry 10 clickhouse-client -q "insert into system.zookeeper (name, path, value) values ('auxiliary_zookeeper2', '/test/chroot/', '')"
TIMEOUT=$((MAX_RUN_TIME - 800 > 8400 ? 8400 : MAX_RUN_TIME - 800))
START_TIME=${SECONDS}
set +e set +e
TEST_ARGS=( TEST_ARGS=(
@ -324,32 +319,22 @@ function run_tests()
--test-runs "$NUM_TRIES" --test-runs "$NUM_TRIES"
"${ADDITIONAL_OPTIONS[@]}" "${ADDITIONAL_OPTIONS[@]}"
) )
timeout --preserve-status --signal TERM --kill-after 60m ${TIMEOUT}s clickhouse-test "${TEST_ARGS[@]}" 2>&1 \ clickhouse-test "${TEST_ARGS[@]}" 2>&1 \
| ts '%Y-%m-%d %H:%M:%S' \ | ts '%Y-%m-%d %H:%M:%S' \
| tee -a test_output/test_result.txt | tee -a test_output/test_result.txt
set -e set -e
DURATION=$((SECONDS - START_TIME))
echo "Elapsed ${DURATION} seconds."
if [[ $DURATION -ge $TIMEOUT ]]
then
echo "It looks like the command is terminated by the timeout, which is ${TIMEOUT} seconds."
fi
} }
export -f run_tests export -f run_tests
# This should be enough to setup job and collect artifacts
TIMEOUT=$((MAX_RUN_TIME - 700))
if [ "$NUM_TRIES" -gt "1" ]; then if [ "$NUM_TRIES" -gt "1" ]; then
# We don't run tests with Ordinary database in PRs, only in master. # We don't run tests with Ordinary database in PRs, only in master.
# So run new/changed tests with Ordinary at least once in flaky check. # So run new/changed tests with Ordinary at least once in flaky check.
timeout_with_logging "$TIMEOUT" bash -c 'NUM_TRIES=1; USE_DATABASE_ORDINARY=1; run_tests' \ NUM_TRIES=1; USE_DATABASE_ORDINARY=1; run_tests \
| sed 's/All tests have finished/Redacted: a message about tests finish is deleted/' | sed 's/No tests were run/Redacted: a message about no tests run is deleted/' ||: | sed 's/All tests have finished/Redacted: a message about tests finish is deleted/' | sed 's/No tests were run/Redacted: a message about no tests run is deleted/' ||:
fi fi
timeout_with_logging "$TIMEOUT" bash -c run_tests ||: run_tests ||:
echo "Files in current directory" echo "Files in current directory"
ls -la ./ ls -la ./
@ -391,8 +376,8 @@ done
# wait for minio to flush its batch if it has any # wait for minio to flush its batch if it has any
sleep 1 sleep 1
clickhouse-client -q "SYSTEM FLUSH ASYNC INSERT QUEUE" clickhouse-client -q "SYSTEM FLUSH ASYNC INSERT QUEUE"
clickhouse-client -q "SELECT log FROM minio_audit_logs ORDER BY event_time INTO OUTFILE '/test_output/minio_audit_logs.jsonl.zst' FORMAT JSONEachRow" clickhouse-client --max_block_size 8192 --max_memory_usage 10G --max_threads 1 --max_result_bytes 0 --max_result_rows 0 --max_rows_to_read 0 --max_bytes_to_read 0 -q "SELECT log FROM minio_audit_logs ORDER BY event_time INTO OUTFILE '/test_output/minio_audit_logs.jsonl.zst' FORMAT JSONEachRow"
clickhouse-client -q "SELECT log FROM minio_server_logs ORDER BY event_time INTO OUTFILE '/test_output/minio_server_logs.jsonl.zst' FORMAT JSONEachRow" clickhouse-client --max_block_size 8192 --max_memory_usage 10G --max_threads 1 --max_result_bytes 0 --max_result_rows 0 --max_rows_to_read 0 --max_bytes_to_read 0 -q "SELECT log FROM minio_server_logs ORDER BY event_time INTO OUTFILE '/test_output/minio_server_logs.jsonl.zst' FORMAT JSONEachRow"
# Stop server so we can safely read data with clickhouse-local. # Stop server so we can safely read data with clickhouse-local.
# Why do we read data with clickhouse-local? # Why do we read data with clickhouse-local?

View File

@ -40,22 +40,6 @@ function fn_exists() {
declare -F "$1" > /dev/null; declare -F "$1" > /dev/null;
} }
function timeout_with_logging() {
local exit_code=0
timeout -s TERM --preserve-status "${@}" || exit_code="${?}"
echo "Checking if it is a timeout. The code 124 will indicate a timeout."
if [[ "${exit_code}" -eq "124" ]]
then
echo "The command 'timeout ${*}' has been killed by timeout."
else
echo "No, it isn't a timeout."
fi
return $exit_code
}
function collect_core_dumps() function collect_core_dumps()
{ {
find . -type f -maxdepth 1 -name 'core.*' | while read -r core; do find . -type f -maxdepth 1 -name 'core.*' | while read -r core; do

View File

@ -116,7 +116,7 @@ def process_test_log(log_path, broken_tests):
test[0], test[0],
test[1], test[1],
test[2], test[2],
"".join(test[3])[:4096].replace("\t", "\\t").replace("\n", "\\n"), "".join(test[3])[:8192].replace("\t", "\\t").replace("\n", "\\n"),
] ]
for test in test_results for test in test_results
] ]

View File

@ -0,0 +1,38 @@
---
sidebar_position: 1
sidebar_label: 2024
---
# 2024 Changelog
### ClickHouse release v23.8.16.16-lts (b80cac57ead) FIXME as compared to v23.8.15.35-lts (060ff8e813a)
#### Improvement
* Backported in [#66962](https://github.com/ClickHouse/ClickHouse/issues/66962): Added support for parameterized view with analyzer to not analyze create parameterized view. Refactor existing parameterized view logic to not analyze create parameterized view. [#54211](https://github.com/ClickHouse/ClickHouse/pull/54211) ([SmitaRKulkarni](https://github.com/SmitaRKulkarni)).
* Backported in [#65461](https://github.com/ClickHouse/ClickHouse/issues/65461): Reload certificate chain during certificate reload. [#61671](https://github.com/ClickHouse/ClickHouse/pull/61671) ([Pervakov Grigorii](https://github.com/GrigoryPervakov)).
* Backported in [#65880](https://github.com/ClickHouse/ClickHouse/issues/65880): Always start Keeper with sufficient amount of threads in global thread pool. [#64444](https://github.com/ClickHouse/ClickHouse/pull/64444) ([Duc Canh Le](https://github.com/canhld94)).
* Backported in [#65912](https://github.com/ClickHouse/ClickHouse/issues/65912): Respect cgroup CPU limit in Keeper. [#65819](https://github.com/ClickHouse/ClickHouse/pull/65819) ([Antonio Andelic](https://github.com/antonio2368)).
#### Bug Fix (user-visible misbehavior in an official stable release)
* Backported in [#65351](https://github.com/ClickHouse/ClickHouse/issues/65351): Fix possible abort on uncaught exception in ~WriteBufferFromFileDescriptor in StatusFile. [#64206](https://github.com/ClickHouse/ClickHouse/pull/64206) ([Kruglov Pavel](https://github.com/Avogar)).
* Backported in [#66037](https://github.com/ClickHouse/ClickHouse/issues/66037): Fix crash on destroying AccessControl: add explicit shutdown. [#64993](https://github.com/ClickHouse/ClickHouse/pull/64993) ([Vitaly Baranov](https://github.com/vitlibar)).
* Backported in [#65281](https://github.com/ClickHouse/ClickHouse/issues/65281): Fix crash with UniqInjectiveFunctionsEliminationPass and uniqCombined. [#65188](https://github.com/ClickHouse/ClickHouse/pull/65188) ([Raúl Marín](https://github.com/Algunenano)).
* Backported in [#65368](https://github.com/ClickHouse/ClickHouse/issues/65368): Fix a bug in ClickHouse Keeper that causes digest mismatch during closing session. [#65198](https://github.com/ClickHouse/ClickHouse/pull/65198) ([Aleksei Filatov](https://github.com/aalexfvk)).
* Backported in [#65782](https://github.com/ClickHouse/ClickHouse/issues/65782): Fixed bug in MergeJoin. Column in sparse serialisation might be treated as a column of its nested type though the required conversion wasn't performed. [#65632](https://github.com/ClickHouse/ClickHouse/pull/65632) ([Nikita Taranov](https://github.com/nickitat)).
* Backported in [#65743](https://github.com/ClickHouse/ClickHouse/issues/65743): Fix crash in maxIntersections. [#65689](https://github.com/ClickHouse/ClickHouse/pull/65689) ([Raúl Marín](https://github.com/Algunenano)).
* Backported in [#65926](https://github.com/ClickHouse/ClickHouse/issues/65926): For queries that read from `PostgreSQL`, cancel the internal `PostgreSQL` query if the ClickHouse query is finished. Otherwise, `ClickHouse` query cannot be canceled until the internal `PostgreSQL` query is finished. [#65771](https://github.com/ClickHouse/ClickHouse/pull/65771) ([Maksim Kita](https://github.com/kitaisreal)).
* Backported in [#65822](https://github.com/ClickHouse/ClickHouse/issues/65822): Fix a bug in short circuit logic when old analyzer and dictGetOrDefault is used. [#65802](https://github.com/ClickHouse/ClickHouse/pull/65802) ([jsc0218](https://github.com/jsc0218)).
* Backported in [#66322](https://github.com/ClickHouse/ClickHouse/issues/66322): Add missing settings `input_format_csv_skip_first_lines/input_format_tsv_skip_first_lines/input_format_csv_try_infer_numbers_from_strings/input_format_csv_try_infer_strings_from_quoted_tuples` in schema inference cache because they can change the resulting schema. It prevents from incorrect result of schema inference with these settings changed. [#65980](https://github.com/ClickHouse/ClickHouse/pull/65980) ([Kruglov Pavel](https://github.com/Avogar)).
* Backported in [#66449](https://github.com/ClickHouse/ClickHouse/issues/66449): Fixed a bug in ZooKeeper client: a session could get stuck in unusable state after receiving a hardware error from ZooKeeper. For example, this might happen due to "soft memory limit" in ClickHouse Keeper. [#66140](https://github.com/ClickHouse/ClickHouse/pull/66140) ([Alexander Tokmakov](https://github.com/tavplubix)).
* Backported in [#66717](https://github.com/ClickHouse/ClickHouse/issues/66717): Correctly track memory for `Allocator::realloc`. [#66548](https://github.com/ClickHouse/ClickHouse/pull/66548) ([Antonio Andelic](https://github.com/antonio2368)).
* Backported in [#67320](https://github.com/ClickHouse/ClickHouse/issues/67320): TRUNCATE DATABASE used to stop replication as if it was a DROP DATABASE query, it's fixed. [#67129](https://github.com/ClickHouse/ClickHouse/pull/67129) ([Alexander Tokmakov](https://github.com/tavplubix)).
#### NOT FOR CHANGELOG / INSIGNIFICANT
* Backported in [#65080](https://github.com/ClickHouse/ClickHouse/issues/65080): Follow up to [#56541](https://github.com/ClickHouse/ClickHouse/issues/56541). [#57141](https://github.com/ClickHouse/ClickHouse/pull/57141) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Backported in [#64997](https://github.com/ClickHouse/ClickHouse/issues/64997): Fix crash with DISTINCT and window functions. [#64767](https://github.com/ClickHouse/ClickHouse/pull/64767) ([Igor Nikonov](https://github.com/devcrafter)).
* Backported in [#65913](https://github.com/ClickHouse/ClickHouse/issues/65913): Fix bug with session closing in Keeper. [#65735](https://github.com/ClickHouse/ClickHouse/pull/65735) ([Antonio Andelic](https://github.com/antonio2368)).
* Backported in [#66853](https://github.com/ClickHouse/ClickHouse/issues/66853): Fix data race in S3::ClientCache. [#66644](https://github.com/ClickHouse/ClickHouse/pull/66644) ([Konstantin Morozov](https://github.com/k-morozov)).
* Backported in [#67072](https://github.com/ClickHouse/ClickHouse/issues/67072): Increase asio pool size in case the server is tiny. [#66761](https://github.com/ClickHouse/ClickHouse/pull/66761) ([alesapin](https://github.com/alesapin)).
* Update version after release. [#67691](https://github.com/ClickHouse/ClickHouse/pull/67691) ([robot-clickhouse](https://github.com/robot-clickhouse)).

View File

@ -0,0 +1,16 @@
---
sidebar_position: 1
sidebar_label: 2024
---
# 2024 Changelog
### ClickHouse release v24.3.8.13-lts (84bbfc70f5d) FIXME as compared to v24.3.7.30-lts (c8a28cf4331)
#### Bug Fix (user-visible misbehavior in an official stable release)
* Backported in [#68562](https://github.com/ClickHouse/ClickHouse/issues/68562): Fix indexHint function case found by fuzzer. [#66286](https://github.com/ClickHouse/ClickHouse/pull/66286) ([Anton Popov](https://github.com/CurtizJ)).
* Backported in [#68114](https://github.com/ClickHouse/ClickHouse/issues/68114): Fix possible PARAMETER_OUT_OF_BOUND error during reading variant subcolumn. [#66659](https://github.com/ClickHouse/ClickHouse/pull/66659) ([Kruglov Pavel](https://github.com/Avogar)).
* Backported in [#67989](https://github.com/ClickHouse/ClickHouse/issues/67989): Validate experimental/suspicious data types in ALTER ADD/MODIFY COLUMN. [#67911](https://github.com/ClickHouse/ClickHouse/pull/67911) ([Kruglov Pavel](https://github.com/Avogar)).
* Backported in [#68335](https://github.com/ClickHouse/ClickHouse/issues/68335): Try fix postgres crash when query is cancelled. [#68288](https://github.com/ClickHouse/ClickHouse/pull/68288) ([Kseniia Sumarokova](https://github.com/kssenii)).
* Backported in [#68392](https://github.com/ClickHouse/ClickHouse/issues/68392): Fix missing sync replica mode in query `SYSTEM SYNC REPLICA`. [#68326](https://github.com/ClickHouse/ClickHouse/pull/68326) ([Duc Canh Le](https://github.com/canhld94)).

View File

@ -1381,7 +1381,7 @@ Default value: `2`.
Close connection before returning connection to the pool. Close connection before returning connection to the pool.
Default value: true. Default value: false.
## odbc_bridge_connection_pool_size {#odbc-bridge-connection-pool-size} ## odbc_bridge_connection_pool_size {#odbc-bridge-connection-pool-size}

View File

@ -6103,30 +6103,23 @@ Result:
└───────┴───────────────┴──────┴──────────────┴──────────────┴──────────────────────┘ └───────┴───────────────┴──────┴──────────────┴──────────────┴──────────────────────┘
``` ```
## toInterval(Year\|Quarter\|Month\|Week\|Day\|Hour\|Minute\|Second) ## toIntervalYear
Converts a Number type argument to an [Interval](../data-types/special-data-types/interval.md) data type. Returns an interval of `n` years of data type [IntervalYear](../data-types/special-data-types/interval.md).
**Syntax** **Syntax**
``` sql ``` sql
toIntervalSecond(number) toIntervalYear(n)
toIntervalMinute(number)
toIntervalHour(number)
toIntervalDay(number)
toIntervalWeek(number)
toIntervalMonth(number)
toIntervalQuarter(number)
toIntervalYear(number)
``` ```
**Arguments** **Arguments**
- `number` — Duration of interval. Positive integer number. - `n` — Number of years. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values** **Returned values**
- The value in `Interval` data type. - Interval of `n` years. [IntervalYear](../data-types/special-data-types/interval.md).
**Example** **Example**
@ -6134,20 +6127,387 @@ Query:
``` sql ``` sql
WITH WITH
toDate('2019-01-01') AS date, toDate('2024-06-15') AS date,
INTERVAL 1 WEEK AS interval_week, toIntervalYear(1) AS interval_to_year
toIntervalWeek(1) AS interval_to_week SELECT date + interval_to_year AS result
SELECT
date + interval_week,
date + interval_to_week;
``` ```
Result: Result:
```response ```response
┌─plus(date, interval_week)─┬─plus(date, interval_to_week)─┐ ┌─────result─┐
│ 2019-01-08 │ 2019-01-08 │ │ 2025-06-15 │
└───────────────────────────┴──────────────────────────────┘ └────────────┘
```
## toIntervalQuarter
Returns an interval of `n` quarters of data type [IntervalQuarter](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalQuarter(n)
```
**Arguments**
- `n` — Number of quarters. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` quarters. [IntervalQuarter](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalQuarter(1) AS interval_to_quarter
SELECT date + interval_to_quarter AS result
```
Result:
```response
┌─────result─┐
│ 2024-09-15 │
└────────────┘
```
## toIntervalMonth
Returns an interval of `n` months of data type [IntervalMonth](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalMonth(n)
```
**Arguments**
- `n` — Number of months. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` months. [IntervalMonth](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalMonth(1) AS interval_to_month
SELECT date + interval_to_month AS result
```
Result:
```response
┌─────result─┐
│ 2024-07-15 │
└────────────┘
```
## toIntervalWeek
Returns an interval of `n` weeks of data type [IntervalWeek](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalWeek(n)
```
**Arguments**
- `n` — Number of weeks. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` weeks. [IntervalWeek](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalWeek(1) AS interval_to_week
SELECT date + interval_to_week AS result
```
Result:
```response
┌─────result─┐
│ 2024-06-22 │
└────────────┘
```
## toIntervalDay
Returns an interval of `n` days of data type [IntervalDay](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalDay(n)
```
**Arguments**
- `n` — Number of days. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` days. [IntervalDay](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalDay(5) AS interval_to_days
SELECT date + interval_to_days AS result
```
Result:
```response
┌─────result─┐
│ 2024-06-20 │
└────────────┘
```
## toIntervalHour
Returns an interval of `n` hours of data type [IntervalHour](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalHour(n)
```
**Arguments**
- `n` — Number of hours. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` hours. [IntervalHour](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalHour(12) AS interval_to_hours
SELECT date + interval_to_hours AS result
```
Result:
```response
┌──────────────result─┐
│ 2024-06-15 12:00:00 │
└─────────────────────┘
```
## toIntervalMinute
Returns an interval of `n` minutes of data type [IntervalMinute](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalMinute(n)
```
**Arguments**
- `n` — Number of minutes. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` minutes. [IntervalMinute](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalMinute(12) AS interval_to_minutes
SELECT date + interval_to_minutes AS result
```
Result:
```response
┌──────────────result─┐
│ 2024-06-15 00:12:00 │
└─────────────────────┘
```
## toIntervalSecond
Returns an interval of `n` seconds of data type [IntervalSecond](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalSecond(n)
```
**Arguments**
- `n` — Number of seconds. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` seconds. [IntervalSecond](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDate('2024-06-15') AS date,
toIntervalSecond(30) AS interval_to_seconds
SELECT date + interval_to_seconds AS result
```
Result:
```response
┌──────────────result─┐
│ 2024-06-15 00:00:30 │
└─────────────────────┘
```
## toIntervalMillisecond
Returns an interval of `n` milliseconds of data type [IntervalMillisecond](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalMillisecond(n)
```
**Arguments**
- `n` — Number of milliseconds. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` milliseconds. [IntervalMilliseconds](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDateTime('2024-06-15') AS date,
toIntervalMillisecond(30) AS interval_to_milliseconds
SELECT date + interval_to_milliseconds AS result
```
Result:
```response
┌──────────────────result─┐
│ 2024-06-15 00:00:00.030 │
└─────────────────────────┘
```
## toIntervalMicrosecond
Returns an interval of `n` microseconds of data type [IntervalMicrosecond](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalMicrosecond(n)
```
**Arguments**
- `n` — Number of microseconds. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` microseconds. [IntervalMicrosecond](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDateTime('2024-06-15') AS date,
toIntervalMicrosecond(30) AS interval_to_microseconds
SELECT date + interval_to_microseconds AS result
```
Result:
```response
┌─────────────────────result─┐
│ 2024-06-15 00:00:00.000030 │
└────────────────────────────┘
```
## toIntervalNanosecond
Returns an interval of `n` nanoseconds of data type [IntervalNanosecond](../data-types/special-data-types/interval.md).
**Syntax**
``` sql
toIntervalNanosecond(n)
```
**Arguments**
- `n` — Number of nanoseconds. Integer numbers or string representations thereof, and float numbers. [(U)Int*](../data-types/int-uint.md)/[Float*](../data-types/float.md)/[String](../data-types/string.md).
**Returned values**
- Interval of `n` nanoseconds. [IntervalNanosecond](../data-types/special-data-types/interval.md).
**Example**
Query:
``` sql
WITH
toDateTime('2024-06-15') AS date,
toIntervalNanosecond(30) AS interval_to_nanoseconds
SELECT date + interval_to_nanoseconds AS result
```
Result:
```response
┌────────────────────────result─┐
│ 2024-06-15 00:00:00.000000030 │
└───────────────────────────────┘
``` ```
## parseDateTime ## parseDateTime

View File

@ -200,6 +200,7 @@ Hierarchy of privileges:
- `JDBC` - `JDBC`
- `HDFS` - `HDFS`
- `S3` - `S3`
- `POSTGRES`
- [dictGet](#dictget) - [dictGet](#dictget)
- [displaySecretsInShowAndSelect](#displaysecretsinshowandselect) - [displaySecretsInShowAndSelect](#displaysecretsinshowandselect)
- [NAMED COLLECTION ADMIN](#named-collection-admin) - [NAMED COLLECTION ADMIN](#named-collection-admin)
@ -476,6 +477,7 @@ Allows using external data sources. Applies to [table engines](../../engines/tab
- `JDBC`. Level: `GLOBAL` - `JDBC`. Level: `GLOBAL`
- `HDFS`. Level: `GLOBAL` - `HDFS`. Level: `GLOBAL`
- `S3`. Level: `GLOBAL` - `S3`. Level: `GLOBAL`
- `POSTGRES`. Level: `GLOBAL`
The `SOURCES` privilege enables use of all the sources. Also you can grant a privilege for each source individually. To use sources, you need additional privileges. The `SOURCES` privilege enables use of all the sources. Also you can grant a privilege for each source individually. To use sources, you need additional privileges.

View File

@ -6,6 +6,7 @@ macro(configure_bash_completion)
COMMAND ${PKG_CONFIG_BIN} --variable=completionsdir bash-completion COMMAND ${PKG_CONFIG_BIN} --variable=completionsdir bash-completion
OUTPUT_VARIABLE ${out} OUTPUT_VARIABLE ${out}
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
) )
endif() endif()
string(REPLACE /usr "${CMAKE_INSTALL_PREFIX}" out "${out}") string(REPLACE /usr "${CMAKE_INSTALL_PREFIX}" out "${out}")

View File

@ -1164,6 +1164,9 @@ void Client::processOptions(const OptionsDescription & options_description,
/// (There is no need to copy the context because clickhouse-client has no background tasks so it won't use that context in parallel.) /// (There is no need to copy the context because clickhouse-client has no background tasks so it won't use that context in parallel.)
client_context = global_context; client_context = global_context;
initClientContext(); initClientContext();
/// Allow to pass-through unknown settings to the server.
client_context->getAccessControl().allowAllSettings();
} }

View File

@ -53,6 +53,9 @@
</proto_caps> </proto_caps>
--> -->
<!-- Do not send clickhouse-client to background on C-z -->
<!-- <ignore_shell_suspend>true</ignore_shell_suspend> -->
<!-- <!--
Settings adjustable via command-line parameters Settings adjustable via command-line parameters
can take their defaults from that config file, see examples: can take their defaults from that config file, see examples:

View File

@ -247,6 +247,7 @@ void DisksApp::runInteractiveReplxx()
suggest, suggest,
history_file, history_file,
/* multiline= */ false, /* multiline= */ false,
/* ignore_shell_suspend= */ false,
query_extenders, query_extenders,
query_delimiters, query_delimiters,
word_break_characters.c_str(), word_break_characters.c_str(),

View File

@ -2,7 +2,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <Client/ReplxxLineReader.h> #include <Client/LineReader.h>
#include <Loggers/Loggers.h> #include <Loggers/Loggers.h>
#include "DisksClient.h" #include "DisksClient.h"
#include "ICommand_fwd.h" #include "ICommand_fwd.h"

View File

@ -1,6 +1,5 @@
#include "DisksClient.h" #include "DisksClient.h"
#include <Client/ClientBase.h> #include <Client/ClientBase.h>
#include <Client/ReplxxLineReader.h>
#include <Disks/registerDisks.h> #include <Disks/registerDisks.h>
#include <Common/Config/ConfigProcessor.h> #include <Common/Config/ConfigProcessor.h>

View File

@ -5,9 +5,8 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <Client/ReplxxLineReader.h>
#include <Loggers/Loggers.h> #include <Loggers/Loggers.h>
#include "Disks/IDisk.h" #include <Disks/IDisk.h>
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <boost/program_options/options_description.hpp> #include <boost/program_options/options_description.hpp>

View File

@ -264,7 +264,11 @@ int mainEntryClickHouseFormat(int argc, char ** argv)
if (!backslash) if (!backslash)
{ {
WriteBufferFromOwnString str_buf; WriteBufferFromOwnString str_buf;
formatAST(*res, str_buf, hilite, oneline || approx_query_length < max_line_length); bool oneline_current_query = oneline || approx_query_length < max_line_length;
IAST::FormatSettings settings(str_buf, oneline_current_query, hilite);
settings.show_secrets = true;
settings.print_pretty_type_names = !oneline_current_query;
res->format(settings);
if (insert_query_payload) if (insert_query_payload)
{ {
@ -307,7 +311,11 @@ int mainEntryClickHouseFormat(int argc, char ** argv)
else else
{ {
WriteBufferFromOwnString str_buf; WriteBufferFromOwnString str_buf;
formatAST(*res, str_buf, hilite, oneline); bool oneline_current_query = oneline || approx_query_length < max_line_length;
IAST::FormatSettings settings(str_buf, oneline_current_query, hilite);
settings.show_secrets = true;
settings.print_pretty_type_names = !oneline_current_query;
res->format(settings);
auto res_string = str_buf.str(); auto res_string = str_buf.str();
WriteBufferFromOStream res_cout(std::cout, 4096); WriteBufferFromOStream res_cout(std::cout, 4096);

View File

@ -314,6 +314,7 @@ void KeeperClient::runInteractiveReplxx()
suggest, suggest,
history_file, history_file,
/* multiline= */ false, /* multiline= */ false,
/* ignore_shell_suspend= */ false,
query_extenders, query_extenders,
query_delimiters, query_delimiters,
word_break_characters, word_break_characters,

View File

@ -66,6 +66,8 @@
/// A minimal file used when the keeper is run without installation /// A minimal file used when the keeper is run without installation
INCBIN(keeper_resource_embedded_xml, SOURCE_DIR "/programs/keeper/keeper_embedded.xml"); INCBIN(keeper_resource_embedded_xml, SOURCE_DIR "/programs/keeper/keeper_embedded.xml");
extern const char * GIT_HASH;
int mainEntryClickHouseKeeper(int argc, char ** argv) int mainEntryClickHouseKeeper(int argc, char ** argv)
{ {
DB::Keeper app; DB::Keeper app;
@ -675,7 +677,7 @@ void Keeper::logRevision() const
"Starting ClickHouse Keeper {} (revision: {}, git hash: {}, build id: {}), PID {}", "Starting ClickHouse Keeper {} (revision: {}, git hash: {}, build id: {}), PID {}",
VERSION_STRING, VERSION_STRING,
ClickHouseRevision::getVersionRevision(), ClickHouseRevision::getVersionRevision(),
git_hash.empty() ? "<unknown>" : git_hash, GIT_HASH,
build_id.empty() ? "<unknown>" : build_id, build_id.empty() ? "<unknown>" : build_id,
getpid()); getpid());
} }

View File

@ -367,7 +367,7 @@ std::string LocalServer::getInitialCreateTableQuery()
else else
table_structure = "(" + table_structure + ")"; table_structure = "(" + table_structure + ")";
return fmt::format("CREATE TABLE {} {} ENGINE = File({}, {});", return fmt::format("CREATE TEMPORARY TABLE {} {} ENGINE = File({}, {});",
table_name, table_structure, data_format, table_file); table_name, table_structure, data_format, table_file);
} }
@ -713,7 +713,7 @@ void LocalServer::processConfig()
if (index_uncompressed_cache_size > max_cache_size) if (index_uncompressed_cache_size > max_cache_size)
{ {
index_uncompressed_cache_size = max_cache_size; index_uncompressed_cache_size = max_cache_size;
LOG_INFO(log, "Lowered index uncompressed cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered index uncompressed cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(index_uncompressed_cache_size));
} }
global_context->setIndexUncompressedCache(index_uncompressed_cache_policy, index_uncompressed_cache_size, index_uncompressed_cache_size_ratio); global_context->setIndexUncompressedCache(index_uncompressed_cache_policy, index_uncompressed_cache_size, index_uncompressed_cache_size_ratio);
@ -723,7 +723,7 @@ void LocalServer::processConfig()
if (index_mark_cache_size > max_cache_size) if (index_mark_cache_size > max_cache_size)
{ {
index_mark_cache_size = max_cache_size; index_mark_cache_size = max_cache_size;
LOG_INFO(log, "Lowered index mark cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered index mark cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(index_mark_cache_size));
} }
global_context->setIndexMarkCache(index_mark_cache_policy, index_mark_cache_size, index_mark_cache_size_ratio); global_context->setIndexMarkCache(index_mark_cache_policy, index_mark_cache_size, index_mark_cache_size_ratio);
@ -731,7 +731,7 @@ void LocalServer::processConfig()
if (mmap_cache_size > max_cache_size) if (mmap_cache_size > max_cache_size)
{ {
mmap_cache_size = max_cache_size; mmap_cache_size = max_cache_size;
LOG_INFO(log, "Lowered mmap file cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered mmap file cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(mmap_cache_size));
} }
global_context->setMMappedFileCache(mmap_cache_size); global_context->setMMappedFileCache(mmap_cache_size);

View File

@ -1420,7 +1420,7 @@ try
if (index_uncompressed_cache_size > max_cache_size) if (index_uncompressed_cache_size > max_cache_size)
{ {
index_uncompressed_cache_size = max_cache_size; index_uncompressed_cache_size = max_cache_size;
LOG_INFO(log, "Lowered index uncompressed cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered index uncompressed cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(index_uncompressed_cache_size));
} }
global_context->setIndexUncompressedCache(index_uncompressed_cache_policy, index_uncompressed_cache_size, index_uncompressed_cache_size_ratio); global_context->setIndexUncompressedCache(index_uncompressed_cache_policy, index_uncompressed_cache_size, index_uncompressed_cache_size_ratio);
@ -1430,7 +1430,7 @@ try
if (index_mark_cache_size > max_cache_size) if (index_mark_cache_size > max_cache_size)
{ {
index_mark_cache_size = max_cache_size; index_mark_cache_size = max_cache_size;
LOG_INFO(log, "Lowered index mark cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered index mark cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(index_mark_cache_size));
} }
global_context->setIndexMarkCache(index_mark_cache_policy, index_mark_cache_size, index_mark_cache_size_ratio); global_context->setIndexMarkCache(index_mark_cache_policy, index_mark_cache_size, index_mark_cache_size_ratio);
@ -1438,7 +1438,7 @@ try
if (mmap_cache_size > max_cache_size) if (mmap_cache_size > max_cache_size)
{ {
mmap_cache_size = max_cache_size; mmap_cache_size = max_cache_size;
LOG_INFO(log, "Lowered mmap file cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered mmap file cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(mmap_cache_size));
} }
global_context->setMMappedFileCache(mmap_cache_size); global_context->setMMappedFileCache(mmap_cache_size);
@ -1449,7 +1449,7 @@ try
if (query_cache_max_size_in_bytes > max_cache_size) if (query_cache_max_size_in_bytes > max_cache_size)
{ {
query_cache_max_size_in_bytes = max_cache_size; query_cache_max_size_in_bytes = max_cache_size;
LOG_INFO(log, "Lowered query cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(uncompressed_cache_size)); LOG_INFO(log, "Lowered query cache size to {} because the system has limited RAM", formatReadableSizeWithBinarySuffix(query_cache_max_size_in_bytes));
} }
global_context->setQueryCache(query_cache_max_size_in_bytes, query_cache_max_entries, query_cache_query_cache_max_entry_size_in_bytes, query_cache_max_entry_size_in_rows); global_context->setQueryCache(query_cache_max_size_in_bytes, query_cache_max_entries, query_cache_query_cache_max_entry_size_in_bytes, query_cache_max_entry_size_in_rows);
@ -1769,6 +1769,8 @@ try
new_server_settings.http_connections_store_limit, new_server_settings.http_connections_store_limit,
}); });
DNSResolver::instance().setFilterSettings(new_server_settings.dns_allow_resolve_names_to_ipv4, new_server_settings.dns_allow_resolve_names_to_ipv6);
if (global_context->isServerCompletelyStarted()) if (global_context->isServerCompletelyStarted())
CannotAllocateThreadFaultInjector::setFaultProbability(new_server_settings.cannot_allocate_thread_fault_injection_probability); CannotAllocateThreadFaultInjector::setFaultProbability(new_server_settings.cannot_allocate_thread_fault_injection_probability);
@ -1920,7 +1922,7 @@ try
auto & access_control = global_context->getAccessControl(); auto & access_control = global_context->getAccessControl();
try try
{ {
access_control.setUpFromMainConfig(config(), config_path, [&] { return global_context->getZooKeeper(); }); access_control.setupFromMainConfig(config(), config_path, [&] { return global_context->getZooKeeper(); });
} }
catch (...) catch (...)
{ {

View File

@ -280,7 +280,7 @@ void AccessControl::shutdown()
} }
void AccessControl::setUpFromMainConfig(const Poco::Util::AbstractConfiguration & config_, const String & config_path_, void AccessControl::setupFromMainConfig(const Poco::Util::AbstractConfiguration & config_, const String & config_path_,
const zkutil::GetZooKeeper & get_zookeeper_function_) const zkutil::GetZooKeeper & get_zookeeper_function_)
{ {
if (config_.has("custom_settings_prefixes")) if (config_.has("custom_settings_prefixes"))
@ -868,4 +868,10 @@ const ExternalAuthenticators & AccessControl::getExternalAuthenticators() const
return *external_authenticators; return *external_authenticators;
} }
void AccessControl::allowAllSettings()
{
custom_settings_prefixes->registerPrefixes({""});
}
} }

View File

@ -57,7 +57,7 @@ public:
void shutdown() override; void shutdown() override;
/// Initializes access storage (user directories). /// Initializes access storage (user directories).
void setUpFromMainConfig(const Poco::Util::AbstractConfiguration & config_, const String & config_path_, void setupFromMainConfig(const Poco::Util::AbstractConfiguration & config_, const String & config_path_,
const zkutil::GetZooKeeper & get_zookeeper_function_); const zkutil::GetZooKeeper & get_zookeeper_function_);
/// Parses access entities from a configuration loaded from users.xml. /// Parses access entities from a configuration loaded from users.xml.
@ -238,6 +238,9 @@ public:
/// Gets manager of notifications. /// Gets manager of notifications.
AccessChangesNotifier & getChangesNotifier(); AccessChangesNotifier & getChangesNotifier();
/// Allow all setting names - this can be used in clients to pass-through unknown settings to the server.
void allowAllSettings();
private: private:
class ContextAccessCache; class ContextAccessCache;
class CustomSettingsPrefixes; class CustomSettingsPrefixes;

View File

@ -82,7 +82,8 @@ public:
Result authenticate(const String & user_name, const String & password) const Result authenticate(const String & user_name, const String & password) const
{ {
Poco::Net::HTTPRequest request{Poco::Net::HTTPRequest::HTTP_GET, this->getURI().getPathAndQuery()}; Poco::Net::HTTPRequest request{
Poco::Net::HTTPRequest::HTTP_GET, this->getURI().getPathAndQuery(), Poco::Net::HTTPRequest::HTTP_1_1};
Poco::Net::HTTPBasicCredentials basic_credentials{user_name, password}; Poco::Net::HTTPBasicCredentials basic_credentials{user_name, password};
basic_credentials.authenticate(request); basic_credentials.authenticate(request);

View File

@ -219,8 +219,8 @@ void SettingsConstraints::clamp(const Settings & current_settings, SettingsChang
}); });
} }
template <class T> template <typename SettingsT>
bool getNewValueToCheck(const T & current_settings, SettingChange & change, Field & new_value, bool throw_on_failure) bool getNewValueToCheck(const SettingsT & current_settings, SettingChange & change, Field & new_value, bool throw_on_failure)
{ {
Field current_value; Field current_value;
bool has_current_value = current_settings.tryGet(change.name, current_value); bool has_current_value = current_settings.tryGet(change.name, current_value);
@ -230,12 +230,12 @@ bool getNewValueToCheck(const T & current_settings, SettingChange & change, Fiel
return false; return false;
if (throw_on_failure) if (throw_on_failure)
new_value = T::castValueUtil(change.name, change.value); new_value = SettingsT::castValueUtil(change.name, change.value);
else else
{ {
try try
{ {
new_value = T::castValueUtil(change.name, change.value); new_value = SettingsT::castValueUtil(change.name, change.value);
} }
catch (...) catch (...)
{ {

View File

@ -114,7 +114,7 @@ private:
{ {
if (ind < first.size()) if (ind < first.size())
return first[ind]; return first[ind];
return second[ind % first.size()]; return second[ind - first.size()];
} }
size_t size() const size_t size() const

View File

@ -58,6 +58,7 @@
#include <QueryPipeline/QueryPipelineBuilder.h> #include <QueryPipeline/QueryPipelineBuilder.h>
#include <Interpreters/ReplaceQueryParameterVisitor.h> #include <Interpreters/ReplaceQueryParameterVisitor.h>
#include <Interpreters/ProfileEventsExt.h> #include <Interpreters/ProfileEventsExt.h>
#include <Interpreters/InterpreterSetQuery.h>
#include <IO/WriteBufferFromOStream.h> #include <IO/WriteBufferFromOStream.h>
#include <IO/WriteBufferFromFileDescriptor.h> #include <IO/WriteBufferFromFileDescriptor.h>
#include <IO/CompressionMethod.h> #include <IO/CompressionMethod.h>
@ -331,7 +332,11 @@ ASTPtr ClientBase::parseQuery(const char *& pos, const char * end, const Setting
{ {
output_stream << std::endl; output_stream << std::endl;
WriteBufferFromOStream res_buf(output_stream, 4096); WriteBufferFromOStream res_buf(output_stream, 4096);
formatAST(*res, res_buf); IAST::FormatSettings format_settings(res_buf, /* one_line */ false);
format_settings.hilite = true;
format_settings.show_secrets = true;
format_settings.print_pretty_type_names = true;
res->format(format_settings);
res_buf.finalize(); res_buf.finalize();
output_stream << std::endl << std::endl; output_stream << std::endl << std::endl;
} }
@ -1604,14 +1609,14 @@ void ClientBase::sendData(Block & sample, const ColumnsDescription & columns_des
auto metadata = storage->getInMemoryMetadataPtr(); auto metadata = storage->getInMemoryMetadataPtr();
QueryPlan plan; QueryPlan plan;
storage->read( storage->read(
plan, plan,
sample.getNames(), sample.getNames(),
storage->getStorageSnapshot(metadata, client_context), storage->getStorageSnapshot(metadata, client_context),
query_info, query_info,
client_context, client_context,
{}, {},
client_context->getSettingsRef().max_block_size, client_context->getSettingsRef().max_block_size,
getNumberOfPhysicalCPUCores()); getNumberOfPhysicalCPUCores());
auto builder = plan.buildQueryPipeline( auto builder = plan.buildQueryPipeline(
QueryPlanOptimizationSettings::fromContext(client_context), QueryPlanOptimizationSettings::fromContext(client_context),
@ -1888,48 +1893,19 @@ void ClientBase::processParsedSingleQuery(const String & full_query, const Strin
profile_events.watch.restart(); profile_events.watch.restart();
{ {
/// Temporarily apply query settings to context. /// Temporarily apply query settings to the context.
std::optional<Settings> old_settings; Settings old_settings = client_context->getSettingsCopy();
SCOPE_EXIT_SAFE({ SCOPE_EXIT_SAFE(
if (old_settings) {
client_context->setSettings(*old_settings); client_context->setSettings(old_settings);
}); });
InterpreterSetQuery::applySettingsFromQuery(parsed_query, client_context);
auto apply_query_settings = [&](const IAST & settings_ast)
{
if (!old_settings)
old_settings.emplace(client_context->getSettingsRef());
client_context->applySettingsChanges(settings_ast.as<ASTSetQuery>()->changes);
client_context->resetSettingsToDefaultValue(settings_ast.as<ASTSetQuery>()->default_settings);
};
const auto * insert = parsed_query->as<ASTInsertQuery>();
if (const auto * select = parsed_query->as<ASTSelectQuery>(); select && select->settings())
apply_query_settings(*select->settings());
else if (const auto * select_with_union = parsed_query->as<ASTSelectWithUnionQuery>())
{
const ASTs & children = select_with_union->list_of_selects->children;
if (!children.empty())
{
// On the client it is enough to apply settings only for the
// last SELECT, since the only thing that is important to apply
// on the client is format settings.
const auto * last_select = children.back()->as<ASTSelectQuery>();
if (last_select && last_select->settings())
{
apply_query_settings(*last_select->settings());
}
}
}
else if (const auto * query_with_output = parsed_query->as<ASTQueryWithOutput>(); query_with_output && query_with_output->settings_ast)
apply_query_settings(*query_with_output->settings_ast);
else if (insert && insert->settings_ast)
apply_query_settings(*insert->settings_ast);
if (!connection->checkConnected(connection_parameters.timeouts)) if (!connection->checkConnected(connection_parameters.timeouts))
connect(); connect();
ASTPtr input_function; ASTPtr input_function;
const auto * insert = parsed_query->as<ASTInsertQuery>();
if (insert && insert->select) if (insert && insert->select)
insert->tryFindInputFunction(input_function); insert->tryFindInputFunction(input_function);
@ -2550,6 +2526,7 @@ void ClientBase::runInteractive()
*suggest, *suggest,
history_file, history_file,
getClientConfiguration().has("multiline"), getClientConfiguration().has("multiline"),
getClientConfiguration().getBool("ignore_shell_suspend", true),
query_extenders, query_extenders,
query_delimiters, query_delimiters,
word_break_characters, word_break_characters,

View File

@ -294,6 +294,7 @@ ReplxxLineReader::ReplxxLineReader(
Suggest & suggest, Suggest & suggest,
const String & history_file_path_, const String & history_file_path_,
bool multiline_, bool multiline_,
bool ignore_shell_suspend,
Patterns extenders_, Patterns extenders_,
Patterns delimiters_, Patterns delimiters_,
const char word_break_characters_[], const char word_break_characters_[],
@ -363,7 +364,8 @@ ReplxxLineReader::ReplxxLineReader(
rx.bind_key(Replxx::KEY::control('P'), [this](char32_t code) { return rx.invoke(Replxx::ACTION::HISTORY_PREVIOUS, code); }); rx.bind_key(Replxx::KEY::control('P'), [this](char32_t code) { return rx.invoke(Replxx::ACTION::HISTORY_PREVIOUS, code); });
/// We don't want the default, "suspend" behavior, it confuses people. /// We don't want the default, "suspend" behavior, it confuses people.
rx.bind_key_internal(replxx::Replxx::KEY::control('Z'), "insert_character"); if (ignore_shell_suspend)
rx.bind_key_internal(replxx::Replxx::KEY::control('Z'), "insert_character");
auto commit_action = [this](char32_t code) auto commit_action = [this](char32_t code)
{ {

View File

@ -15,6 +15,7 @@ public:
Suggest & suggest, Suggest & suggest,
const String & history_file_path, const String & history_file_path,
bool multiline, bool multiline,
bool ignore_shell_suspend,
Patterns extenders_, Patterns extenders_,
Patterns delimiters_, Patterns delimiters_,
const char word_break_characters_[], const char word_break_characters_[],

View File

@ -12,6 +12,7 @@
#include <atomic> #include <atomic>
#include <optional> #include <optional>
#include <string_view> #include <string_view>
#include "Common/MultiVersion.h"
#include <unordered_set> #include <unordered_set>
#include "DNSPTRResolverProvider.h" #include "DNSPTRResolverProvider.h"
@ -139,12 +140,6 @@ DNSResolver::IPAddresses resolveIPAddressImpl(const std::string & host)
return addresses; return addresses;
} }
DNSResolver::IPAddresses resolveIPAddressWithCache(CacheBase<std::string, DNSResolver::CacheEntry> & cache, const std::string & host)
{
auto [result, _ ] = cache.getOrSet(host, [&host]() {return std::make_shared<DNSResolver::CacheEntry>(resolveIPAddressImpl(host), std::chrono::system_clock::now());});
return result->addresses;
}
std::unordered_set<String> reverseResolveImpl(const Poco::Net::IPAddress & address) std::unordered_set<String> reverseResolveImpl(const Poco::Net::IPAddress & address)
{ {
auto ptr_resolver = DB::DNSPTRResolverProvider::get(); auto ptr_resolver = DB::DNSPTRResolverProvider::get();
@ -198,21 +193,89 @@ struct DNSResolver::Impl
std::atomic<bool> disable_cache{false}; std::atomic<bool> disable_cache{false};
}; };
struct DNSResolver::AddressFilter
{
struct DNSFilterSettings
{
bool dns_allow_resolve_names_to_ipv4{true};
bool dns_allow_resolve_names_to_ipv6{true};
};
DNSResolver::DNSResolver() : impl(std::make_unique<DNSResolver::Impl>()), log(getLogger("DNSResolver")) {} AddressFilter() : settings(std::make_unique<DNSFilterSettings>()) {}
void performAddressFiltering(DNSResolver::IPAddresses & addresses) const
{
const auto current_settings = settings.get();
bool dns_resolve_ipv4 = current_settings->dns_allow_resolve_names_to_ipv4;
bool dns_resolve_ipv6 = current_settings->dns_allow_resolve_names_to_ipv6;
if (dns_resolve_ipv4 && dns_resolve_ipv6)
{
return;
}
if (!dns_resolve_ipv4 && !dns_resolve_ipv6)
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "DNS can't resolve any address, because dns_resolve_ipv6_interfaces and dns_resolve_ipv4_interfaces both are disabled");
}
std::erase_if(addresses, [dns_resolve_ipv6, dns_resolve_ipv4](const Poco::Net::IPAddress& address)
{
return (address.family() == Poco::Net::IPAddress::IPv6 && !dns_resolve_ipv6)
|| (address.family() == Poco::Net::IPAddress::IPv4 && !dns_resolve_ipv4);
});
}
void setSettings(bool dns_allow_resolve_names_to_ipv4, bool dns_allow_resolve_names_to_ipv6)
{
settings.set(std::make_unique<DNSFilterSettings>(dns_allow_resolve_names_to_ipv4, dns_allow_resolve_names_to_ipv6));
}
MultiVersion<DNSFilterSettings> settings;
};
DNSResolver::DNSResolver()
: impl(std::make_unique<DNSResolver::Impl>())
, addressFilter(std::make_unique<DNSResolver::AddressFilter>())
, log(getLogger("DNSResolver")) {}
DNSResolver::IPAddresses DNSResolver::getResolvedIPAdressessWithFiltering(const std::string & host)
{
auto addresses = resolveIPAddressImpl(host);
addressFilter->performAddressFiltering(addresses);
if (addresses.empty())
{
ProfileEvents::increment(ProfileEvents::DNSError);
throw DB::NetException(ErrorCodes::DNS_ERROR, "After filtering there are no resolved address for host({}).", host);
}
return addresses;
}
DNSResolver::IPAddresses DNSResolver::resolveIPAddressWithCache(const std::string & host)
{
auto [result, _ ] = impl->cache_host.getOrSet(host, [&host, this]() {return std::make_shared<DNSResolver::CacheEntry>(getResolvedIPAdressessWithFiltering(host), std::chrono::system_clock::now());});
return result->addresses;
}
Poco::Net::IPAddress DNSResolver::resolveHost(const std::string & host) Poco::Net::IPAddress DNSResolver::resolveHost(const std::string & host)
{ {
return pickAddress(resolveHostAll(host)); // random order -> random pick return pickAddress(resolveHostAll(host)); // random order -> random pick
} }
void DNSResolver::setFilterSettings(bool dns_allow_resolve_names_to_ipv4, bool dns_allow_resolve_names_to_ipv6)
{
addressFilter->setSettings(dns_allow_resolve_names_to_ipv4, dns_allow_resolve_names_to_ipv6);
}
DNSResolver::IPAddresses DNSResolver::resolveHostAllInOriginOrder(const std::string & host) DNSResolver::IPAddresses DNSResolver::resolveHostAllInOriginOrder(const std::string & host)
{ {
if (impl->disable_cache) if (impl->disable_cache)
return resolveIPAddressImpl(host); return getResolvedIPAdressessWithFiltering(host);
addToNewHosts(host); addToNewHosts(host);
return resolveIPAddressWithCache(impl->cache_host, host); return resolveIPAddressWithCache(host);
} }
DNSResolver::IPAddresses DNSResolver::resolveHostAll(const std::string & host) DNSResolver::IPAddresses DNSResolver::resolveHostAll(const std::string & host)
@ -232,7 +295,7 @@ Poco::Net::SocketAddress DNSResolver::resolveAddress(const std::string & host_an
splitHostAndPort(host_and_port, host, port); splitHostAndPort(host_and_port, host, port);
addToNewHosts(host); addToNewHosts(host);
return Poco::Net::SocketAddress(pickAddress(resolveIPAddressWithCache(impl->cache_host, host)), port); return Poco::Net::SocketAddress(pickAddress(resolveIPAddressWithCache(host)), port);
} }
Poco::Net::SocketAddress DNSResolver::resolveAddress(const std::string & host, UInt16 port) Poco::Net::SocketAddress DNSResolver::resolveAddress(const std::string & host, UInt16 port)
@ -241,7 +304,7 @@ Poco::Net::SocketAddress DNSResolver::resolveAddress(const std::string & host, U
return Poco::Net::SocketAddress(host, port); return Poco::Net::SocketAddress(host, port);
addToNewHosts(host); addToNewHosts(host);
return Poco::Net::SocketAddress(pickAddress(resolveIPAddressWithCache(impl->cache_host, host)), port); return Poco::Net::SocketAddress(pickAddress(resolveIPAddressWithCache(host)), port);
} }
std::vector<Poco::Net::SocketAddress> DNSResolver::resolveAddressList(const std::string & host, UInt16 port) std::vector<Poco::Net::SocketAddress> DNSResolver::resolveAddressList(const std::string & host, UInt16 port)
@ -254,7 +317,7 @@ std::vector<Poco::Net::SocketAddress> DNSResolver::resolveAddressList(const std:
if (!impl->disable_cache) if (!impl->disable_cache)
addToNewHosts(host); addToNewHosts(host);
std::vector<Poco::Net::IPAddress> ips = impl->disable_cache ? hostByName(host) : resolveIPAddressWithCache(impl->cache_host, host); std::vector<Poco::Net::IPAddress> ips = impl->disable_cache ? hostByName(host) : resolveIPAddressWithCache(host);
auto ips_end = std::unique(ips.begin(), ips.end()); auto ips_end = std::unique(ips.begin(), ips.end());
addresses.reserve(ips_end - ips.begin()); addresses.reserve(ips_end - ips.begin());
@ -419,8 +482,8 @@ bool DNSResolver::updateCache(UInt32 max_consecutive_failures)
bool DNSResolver::updateHost(const String & host) bool DNSResolver::updateHost(const String & host)
{ {
const auto old_value = resolveIPAddressWithCache(impl->cache_host, host); const auto old_value = resolveIPAddressWithCache(host);
auto new_value = resolveIPAddressImpl(host); auto new_value = getResolvedIPAdressessWithFiltering(host);
const bool result = old_value != new_value; const bool result = old_value != new_value;
impl->cache_host.set(host, std::make_shared<DNSResolver::CacheEntry>(std::move(new_value), std::chrono::system_clock::now())); impl->cache_host.set(host, std::make_shared<DNSResolver::CacheEntry>(std::move(new_value), std::chrono::system_clock::now()));
return result; return result;

View File

@ -68,6 +68,8 @@ public:
/// Returns true if IP of any host has been changed or an element was dropped (too many failures) /// Returns true if IP of any host has been changed or an element was dropped (too many failures)
bool updateCache(UInt32 max_consecutive_failures); bool updateCache(UInt32 max_consecutive_failures);
void setFilterSettings(bool dns_allow_resolve_names_to_ipv4, bool dns_allow_resolve_names_to_ipv6);
/// Returns a copy of cache entries /// Returns a copy of cache entries
std::vector<std::pair<std::string, CacheEntry>> cacheEntries() const; std::vector<std::pair<std::string, CacheEntry>> cacheEntries() const;
@ -86,6 +88,10 @@ private:
struct Impl; struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;
struct AddressFilter;
std::unique_ptr<AddressFilter> addressFilter;
LoggerPtr log; LoggerPtr log;
/// Updates cached value and returns true it has been changed. /// Updates cached value and returns true it has been changed.
@ -94,6 +100,9 @@ private:
void addToNewHosts(const String & host); void addToNewHosts(const String & host);
void addToNewAddresses(const Poco::Net::IPAddress & address); void addToNewAddresses(const Poco::Net::IPAddress & address);
IPAddresses resolveIPAddressWithCache(const std::string & host);
IPAddresses getResolvedIPAdressessWithFiltering(const std::string & host);
}; };
} }

View File

@ -112,9 +112,8 @@ namespace
return configuration.has(config_prefix + ".uri"); return configuration.has(config_prefix + ".uri");
} }
/* /* New syntax requires protocol prefix "<http> or <https>"
* New syntax requires protocol prefix "<http> or <https>" */
* */
std::optional<std::string> getProtocolPrefix( std::optional<std::string> getProtocolPrefix(
ProxyConfiguration::Protocol request_protocol, ProxyConfiguration::Protocol request_protocol,
const String & config_prefix, const String & config_prefix,
@ -130,22 +129,18 @@ namespace
return protocol_prefix; return protocol_prefix;
} }
template <bool new_syntax>
std::optional<std::string> calculatePrefixBasedOnSettingsSyntax( std::optional<std::string> calculatePrefixBasedOnSettingsSyntax(
bool new_syntax,
ProxyConfiguration::Protocol request_protocol, ProxyConfiguration::Protocol request_protocol,
const String & config_prefix, const String & config_prefix,
const Poco::Util::AbstractConfiguration & configuration const Poco::Util::AbstractConfiguration & configuration
) )
{ {
if (!configuration.has(config_prefix)) if (!configuration.has(config_prefix))
{
return std::nullopt; return std::nullopt;
}
if constexpr (new_syntax) if (new_syntax)
{
return getProtocolPrefix(request_protocol, config_prefix, configuration); return getProtocolPrefix(request_protocol, config_prefix, configuration);
}
return config_prefix; return config_prefix;
} }
@ -155,24 +150,21 @@ std::shared_ptr<ProxyConfigurationResolver> ProxyConfigurationResolverProvider::
Protocol request_protocol, Protocol request_protocol,
const Poco::Util::AbstractConfiguration & configuration) const Poco::Util::AbstractConfiguration & configuration)
{ {
if (auto resolver = getFromSettings(request_protocol, "proxy", configuration)) if (auto resolver = getFromSettings(true, request_protocol, "proxy", configuration))
{
return resolver; return resolver;
}
return std::make_shared<EnvironmentProxyConfigurationResolver>( return std::make_shared<EnvironmentProxyConfigurationResolver>(
request_protocol, request_protocol,
isTunnelingDisabledForHTTPSRequestsOverHTTPProxy(configuration)); isTunnelingDisabledForHTTPSRequestsOverHTTPProxy(configuration));
} }
template <bool is_new_syntax>
std::shared_ptr<ProxyConfigurationResolver> ProxyConfigurationResolverProvider::getFromSettings( std::shared_ptr<ProxyConfigurationResolver> ProxyConfigurationResolverProvider::getFromSettings(
bool new_syntax,
Protocol request_protocol, Protocol request_protocol,
const String & config_prefix, const String & config_prefix,
const Poco::Util::AbstractConfiguration & configuration const Poco::Util::AbstractConfiguration & configuration)
)
{ {
auto prefix_opt = calculatePrefixBasedOnSettingsSyntax<is_new_syntax>(request_protocol, config_prefix, configuration); auto prefix_opt = calculatePrefixBasedOnSettingsSyntax(new_syntax, request_protocol, config_prefix, configuration);
if (!prefix_opt) if (!prefix_opt)
{ {
@ -195,20 +187,17 @@ std::shared_ptr<ProxyConfigurationResolver> ProxyConfigurationResolverProvider::
std::shared_ptr<ProxyConfigurationResolver> ProxyConfigurationResolverProvider::getFromOldSettingsFormat( std::shared_ptr<ProxyConfigurationResolver> ProxyConfigurationResolverProvider::getFromOldSettingsFormat(
Protocol request_protocol, Protocol request_protocol,
const String & config_prefix, const String & config_prefix,
const Poco::Util::AbstractConfiguration & configuration const Poco::Util::AbstractConfiguration & configuration)
)
{ {
/* /* First try to get it from settings only using the combination of config_prefix and configuration.
* First try to get it from settings only using the combination of config_prefix and configuration.
* This logic exists for backward compatibility with old S3 storage specific proxy configuration. * This logic exists for backward compatibility with old S3 storage specific proxy configuration.
* */ * */
if (auto resolver = ProxyConfigurationResolverProvider::getFromSettings<false>(request_protocol, config_prefix + ".proxy", configuration)) if (auto resolver = ProxyConfigurationResolverProvider::getFromSettings(false, request_protocol, config_prefix + ".proxy", configuration))
{ {
return resolver; return resolver;
} }
/* /* In case the combination of config_prefix and configuration does not provide a resolver, try to get it from general / new settings.
* In case the combination of config_prefix and configuration does not provide a resolver, try to get it from general / new settings.
* Falls back to Environment resolver if no configuration is found. * Falls back to Environment resolver if no configuration is found.
* */ * */
return ProxyConfigurationResolverProvider::get(request_protocol, configuration); return ProxyConfigurationResolverProvider::get(request_protocol, configuration);

View File

@ -33,12 +33,11 @@ public:
); );
private: private:
template <bool is_new_syntax = true>
static std::shared_ptr<ProxyConfigurationResolver> getFromSettings( static std::shared_ptr<ProxyConfigurationResolver> getFromSettings(
bool is_new_syntax,
Protocol protocol, Protocol protocol,
const String & config_prefix, const String & config_prefix,
const Poco::Util::AbstractConfiguration & configuration const Poco::Util::AbstractConfiguration & configuration);
);
}; };
} }

View File

@ -18,13 +18,17 @@
namespace DB namespace DB
{ {
namespace ErrorCodes namespace ErrorCodes
{ {
extern const int CANNOT_SET_SIGNAL_HANDLER; extern const int CANNOT_SET_SIGNAL_HANDLER;
extern const int CANNOT_SEND_SIGNAL; extern const int CANNOT_SEND_SIGNAL;
} }
} }
extern const char * GIT_HASH;
using namespace DB; using namespace DB;
@ -334,7 +338,7 @@ void SignalListener::onTerminate(std::string_view message, UInt32 thread_num) co
size_t pos = message.find('\n'); size_t pos = message.find('\n');
LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) {}", LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) {}",
VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", daemon ? daemon->git_hash : "", thread_num, message.substr(0, pos)); VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", GIT_HASH, thread_num, message.substr(0, pos));
/// Print trace from std::terminate exception line-by-line to make it easy for grep. /// Print trace from std::terminate exception line-by-line to make it easy for grep.
while (pos != std::string_view::npos) while (pos != std::string_view::npos)
@ -368,7 +372,7 @@ try
LOG_FATAL(log, "########## Short fault info ############"); LOG_FATAL(log, "########## Short fault info ############");
LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) Received signal {}", LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) Received signal {}",
VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", daemon ? daemon->git_hash : "", VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", GIT_HASH,
thread_num, sig); thread_num, sig);
std::string signal_description = "Unknown signal"; std::string signal_description = "Unknown signal";
@ -434,13 +438,13 @@ try
if (query_id.empty()) if (query_id.empty())
{ {
LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) (no query) Received signal {} ({})", LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) (no query) Received signal {} ({})",
VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", daemon ? daemon->git_hash : "", VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", GIT_HASH,
thread_num, signal_description, sig); thread_num, signal_description, sig);
} }
else else
{ {
LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) (query_id: {}) (query: {}) Received signal {} ({})", LOG_FATAL(log, "(version {}{}, build id: {}, git hash: {}) (from thread {}) (query_id: {}) (query: {}) Received signal {} ({})",
VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", daemon ? daemon->git_hash : "", VERSION_STRING, VERSION_OFFICIAL, daemon ? daemon->build_id : "", GIT_HASH,
thread_num, query_id, query, signal_description, sig); thread_num, query_id, query, signal_description, sig);
} }

View File

@ -51,7 +51,7 @@ StatusFile::StatusFile(std::string path_, FillFunction fill_)
std::string contents; std::string contents;
{ {
ReadBufferFromFile in(path, 1024); ReadBufferFromFile in(path, 1024);
LimitReadBuffer limit_in(in, 1024, /* trow_exception */ false, /* exact_limit */ {}); LimitReadBuffer limit_in(in, 1024, /* throw_exception */ false, /* exact_limit */ {});
readStringUntilEOF(contents, limit_in); readStringUntilEOF(contents, limit_in);
} }

View File

@ -92,3 +92,8 @@ endif()
clickhouse_add_executable (check_pointer_valid check_pointer_valid.cpp) clickhouse_add_executable (check_pointer_valid check_pointer_valid.cpp)
target_link_libraries (check_pointer_valid PRIVATE clickhouse_common_io clickhouse_common_config) target_link_libraries (check_pointer_valid PRIVATE clickhouse_common_io clickhouse_common_config)
if (TARGET ch_contrib::icu)
clickhouse_add_executable (utf8_upper_lower utf8_upper_lower.cpp)
target_link_libraries (utf8_upper_lower PRIVATE ch_contrib::icu)
endif ()

View File

@ -0,0 +1,27 @@
#include <iostream>
#include <unicode/unistr.h>
std::string utf8_to_lower(const std::string & input)
{
icu::UnicodeString unicodeInput(input.c_str(), "UTF-8");
unicodeInput.toLower();
std::string output;
unicodeInput.toUTF8String(output);
return output;
}
std::string utf8_to_upper(const std::string & input)
{
icu::UnicodeString unicodeInput(input.c_str(), "UTF-8");
unicodeInput.toUpper();
std::string output;
unicodeInput.toUTF8String(output);
return output;
}
int main()
{
std::string input = "ır";
std::cout << "upper:" << utf8_to_upper(input) << std::endl;
return 0;
}

View File

@ -85,7 +85,7 @@ void BaseExternalTable::parseStructureFromStructureField(const std::string & arg
/// We use `formatWithPossiblyHidingSensitiveData` instead of `getColumnNameWithoutAlias` because `column->type` is an ASTFunction. /// We use `formatWithPossiblyHidingSensitiveData` instead of `getColumnNameWithoutAlias` because `column->type` is an ASTFunction.
/// `getColumnNameWithoutAlias` will return name of the function with `(arguments)` even if arguments is empty. /// `getColumnNameWithoutAlias` will return name of the function with `(arguments)` even if arguments is empty.
if (column) if (column)
structure.emplace_back(column->name, column->type->formatWithPossiblyHidingSensitiveData(0, true, true)); structure.emplace_back(column->name, column->type->formatWithPossiblyHidingSensitiveData(0, true, true, false));
else else
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: expected column definition, got {}", child->formatForErrorMessage()); throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: expected column definition, got {}", child->formatForErrorMessage());
} }
@ -102,7 +102,7 @@ void BaseExternalTable::parseStructureFromTypesField(const std::string & argumen
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: {}", error); throw Exception(ErrorCodes::BAD_ARGUMENTS, "Error while parsing table structure: {}", error);
for (size_t i = 0; i < type_list_raw->children.size(); ++i) for (size_t i = 0; i < type_list_raw->children.size(); ++i)
structure.emplace_back("_" + toString(i + 1), type_list_raw->children[i]->formatWithPossiblyHidingSensitiveData(0, true, true)); structure.emplace_back("_" + toString(i + 1), type_list_raw->children[i]->formatWithPossiblyHidingSensitiveData(0, true, true, false));
} }
void BaseExternalTable::initSampleBlock() void BaseExternalTable::initSampleBlock()

View File

@ -23,7 +23,7 @@ namespace postgres
{ {
PoolWithFailover::PoolWithFailover( PoolWithFailover::PoolWithFailover(
const DB::ExternalDataSourcesConfigurationByPriority & configurations_by_priority, const ReplicasConfigurationByPriority & configurations_by_priority,
size_t pool_size, size_t pool_size,
size_t pool_wait_timeout_, size_t pool_wait_timeout_,
size_t max_tries_, size_t max_tries_,

View File

@ -8,7 +8,6 @@
#include "ConnectionHolder.h" #include "ConnectionHolder.h"
#include <mutex> #include <mutex>
#include <Poco/Util/AbstractConfiguration.h> #include <Poco/Util/AbstractConfiguration.h>
#include <Storages/ExternalDataSourceConfiguration.h>
#include <Storages/StoragePostgreSQL.h> #include <Storages/StoragePostgreSQL.h>
@ -20,12 +19,12 @@ namespace postgres
class PoolWithFailover class PoolWithFailover
{ {
using RemoteDescription = std::vector<std::pair<String, uint16_t>>;
public: public:
using ReplicasConfigurationByPriority = std::map<size_t, std::vector<DB::StoragePostgreSQL::Configuration>>;
using RemoteDescription = std::vector<std::pair<String, uint16_t>>;
PoolWithFailover( PoolWithFailover(
const DB::ExternalDataSourcesConfigurationByPriority & configurations_by_priority, const ReplicasConfigurationByPriority & configurations_by_priority,
size_t pool_size, size_t pool_size,
size_t pool_wait_timeout, size_t pool_wait_timeout,
size_t max_tries_, size_t max_tries_,

View File

@ -106,6 +106,8 @@ namespace DB
M(UInt64, dns_cache_max_entries, 10000, "Internal DNS cache max entries.", 0) \ M(UInt64, dns_cache_max_entries, 10000, "Internal DNS cache max entries.", 0) \
M(Int32, dns_cache_update_period, 15, "Internal DNS cache update period in seconds.", 0) \ M(Int32, dns_cache_update_period, 15, "Internal DNS cache update period in seconds.", 0) \
M(UInt32, dns_max_consecutive_failures, 10, "Max DNS resolve failures of a hostname before dropping the hostname from ClickHouse DNS cache.", 0) \ M(UInt32, dns_max_consecutive_failures, 10, "Max DNS resolve failures of a hostname before dropping the hostname from ClickHouse DNS cache.", 0) \
M(Bool, dns_allow_resolve_names_to_ipv4, true, "Allows resolve names to ipv4 addresses.", 0) \
M(Bool, dns_allow_resolve_names_to_ipv6, true, "Allows resolve names to ipv6 addresses.", 0) \
\ \
M(UInt64, max_table_size_to_drop, 50000000000lu, "If size of a table is greater than this value (in bytes) than table could not be dropped with any DROP query.", 0) \ M(UInt64, max_table_size_to_drop, 50000000000lu, "If size of a table is greater than this value (in bytes) than table could not be dropped with any DROP query.", 0) \
M(UInt64, max_partition_size_to_drop, 50000000000lu, "Same as max_table_size_to_drop, but for the partitions.", 0) \ M(UInt64, max_partition_size_to_drop, 50000000000lu, "Same as max_table_size_to_drop, but for the partitions.", 0) \

View File

@ -882,7 +882,7 @@ class IColumn;
M(Bool, use_json_alias_for_old_object_type, false, "When enabled, JSON type alias will create old experimental Object type instead of a new JSON type", 0) \ M(Bool, use_json_alias_for_old_object_type, false, "When enabled, JSON type alias will create old experimental Object type instead of a new JSON type", 0) \
M(Bool, allow_create_index_without_type, false, "Allow CREATE INDEX query without TYPE. Query will be ignored. Made for SQL compatibility tests.", 0) \ M(Bool, allow_create_index_without_type, false, "Allow CREATE INDEX query without TYPE. Query will be ignored. Made for SQL compatibility tests.", 0) \
M(Bool, create_index_ignore_unique, false, "Ignore UNIQUE keyword in CREATE UNIQUE INDEX. Made for SQL compatibility tests.", 0) \ M(Bool, create_index_ignore_unique, false, "Ignore UNIQUE keyword in CREATE UNIQUE INDEX. Made for SQL compatibility tests.", 0) \
M(Bool, print_pretty_type_names, true, "Print pretty type names in DESCRIBE query and toTypeName() function", 0) \ M(Bool, print_pretty_type_names, true, "Print pretty type names in the DESCRIBE query and `toTypeName` function, as well as in the `SHOW CREATE TABLE` query and the `formatQuery` function.", 0) \
M(Bool, create_table_empty_primary_key_by_default, false, "Allow to create *MergeTree tables with empty primary key when ORDER BY and PRIMARY KEY not specified", 0) \ M(Bool, create_table_empty_primary_key_by_default, false, "Allow to create *MergeTree tables with empty primary key when ORDER BY and PRIMARY KEY not specified", 0) \
M(Bool, allow_named_collection_override_by_default, true, "Allow named collections' fields override by default.", 0) \ M(Bool, allow_named_collection_override_by_default, true, "Allow named collections' fields override by default.", 0) \
M(SQLSecurityType, default_normal_view_sql_security, SQLSecurityType::INVOKER, "Allows to set a default value for SQL SECURITY option when creating a normal view.", 0) \ M(SQLSecurityType, default_normal_view_sql_security, SQLSecurityType::INVOKER, "Allows to set a default value for SQL SECURITY option when creating a normal view.", 0) \

View File

@ -16,39 +16,29 @@
#include <sys/resource.h> #include <sys/resource.h>
#if defined(OS_LINUX) #if defined(OS_LINUX)
#include <sys/prctl.h> #include <sys/prctl.h>
#endif #endif
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <unistd.h> #include <unistd.h>
#include <algorithm> #include <algorithm>
#include <typeinfo> #include <typeinfo>
#include <iostream> #include <iostream>
#include <fstream>
#include <memory> #include <memory>
#include <base/scope_guard.h>
#include <Poco/Message.h> #include <Poco/Message.h>
#include <Poco/Util/Application.h> #include <Poco/Util/Application.h>
#include <Poco/Exception.h> #include <Poco/Exception.h>
#include <Poco/ErrorHandler.h> #include <Poco/ErrorHandler.h>
#include <Poco/Pipe.h> #include <Poco/Pipe.h>
#include <Common/ErrorHandlers.h> #include <Common/ErrorHandlers.h>
#include <Common/SignalHandlers.h> #include <Common/SignalHandlers.h>
#include <base/argsToConfig.h> #include <base/argsToConfig.h>
#include <base/getThreadId.h>
#include <base/coverage.h> #include <base/coverage.h>
#include <base/sleep.h>
#include <IO/WriteBufferFromFileDescriptorDiscardOnFailure.h> #include <IO/WriteBufferFromFileDescriptorDiscardOnFailure.h>
#include <IO/ReadBufferFromFileDescriptor.h>
#include <IO/ReadHelpers.h> #include <IO/ReadHelpers.h>
#include <IO/WriteHelpers.h>
#include <Common/Exception.h> #include <Common/Exception.h>
#include <Common/PipeFDs.h>
#include <Common/StackTrace.h>
#include <Common/getMultipleKeysFromConfig.h> #include <Common/getMultipleKeysFromConfig.h>
#include <Common/ClickHouseRevision.h> #include <Common/ClickHouseRevision.h>
#include <Common/Config/ConfigProcessor.h> #include <Common/Config/ConfigProcessor.h>
@ -459,17 +449,9 @@ void BaseDaemon::initializeTerminationAndSignalProcessing()
signal_listener_thread.start(*signal_listener); signal_listener_thread.start(*signal_listener);
#if defined(__ELF__) && !defined(OS_FREEBSD) #if defined(__ELF__) && !defined(OS_FREEBSD)
String build_id_hex = SymbolIndex::instance().getBuildIDHex(); build_id = SymbolIndex::instance().getBuildIDHex();
if (build_id_hex.empty())
build_id = "";
else
build_id = build_id_hex;
#else
build_id = "";
#endif #endif
git_hash = GIT_HASH;
#if defined(OS_LINUX) #if defined(OS_LINUX)
std::string executable_path = getExecutablePath(); std::string executable_path = getExecutablePath();
@ -482,7 +464,7 @@ void BaseDaemon::logRevision() const
{ {
logger().information("Starting " + std::string{VERSION_FULL} logger().information("Starting " + std::string{VERSION_FULL}
+ " (revision: " + std::to_string(ClickHouseRevision::getVersionRevision()) + " (revision: " + std::to_string(ClickHouseRevision::getVersionRevision())
+ ", git hash: " + (git_hash.empty() ? "<unknown>" : git_hash) + ", git hash: " + std::string(GIT_HASH)
+ ", build id: " + (build_id.empty() ? "<unknown>" : build_id) + ")" + ", build id: " + (build_id.empty() ? "<unknown>" : build_id) + ")"
+ ", PID " + std::to_string(getpid())); + ", PID " + std::to_string(getpid()));
} }

View File

@ -165,7 +165,6 @@ protected:
Poco::Util::AbstractConfiguration * last_configuration = nullptr; Poco::Util::AbstractConfiguration * last_configuration = nullptr;
String build_id; String build_id;
String git_hash;
String stored_binary_hash; String stored_binary_hash;
bool should_setup_watchdog = false; bool should_setup_watchdog = false;

View File

@ -1,10 +1,7 @@
configure_file(GitHash.cpp.in GitHash.generated.cpp)
add_library (daemon add_library (daemon
BaseDaemon.cpp BaseDaemon.cpp
GraphiteWriter.cpp GraphiteWriter.cpp
SentryWriter.cpp SentryWriter.cpp
GitHash.generated.cpp
) )
target_link_libraries (daemon PUBLIC loggers common PRIVATE clickhouse_parsers clickhouse_common_io clickhouse_common_config) target_link_libraries (daemon PUBLIC loggers common PRIVATE clickhouse_parsers clickhouse_common_io clickhouse_common_config)

View File

@ -18,13 +18,15 @@
#include <Core/Settings.h> #include <Core/Settings.h>
#include <IO/Operators.h> #include <IO/Operators.h>
#include "config.h"
#if USE_SIMDJSON #if USE_SIMDJSON
#include <Common/JSONParsers/SimdJSONParser.h> # include <Common/JSONParsers/SimdJSONParser.h>
#elif USE_RAPIDJSON
# include <Common/JSONParsers/RapidJSONParser.h>
#else
# include <Common/JSONParsers/DummyJSONParser.h>
#endif #endif
#if USE_RAPIDJSON
#include <Common/JSONParsers/RapidJSONParser.h>
#endif
#include <Common/JSONParsers/DummyJSONParser.h>
namespace DB namespace DB
{ {
@ -105,7 +107,7 @@ SerializationPtr DataTypeObject::doGetDefaultSerialization() const
switch (schema_format) switch (schema_format)
{ {
case SchemaFormat::JSON: case SchemaFormat::JSON:
#ifdef USE_SIMDJSON #if USE_SIMDJSON
return std::make_shared<SerializationJSON<SimdJSONParser>>( return std::make_shared<SerializationJSON<SimdJSONParser>>(
std::move(typed_path_serializations), std::move(typed_path_serializations),
paths_to_skip, paths_to_skip,

View File

@ -8,7 +8,6 @@
#include <Common/quoteString.h> #include <Common/quoteString.h>
#include <IO/WriteHelpers.h> #include <IO/WriteHelpers.h>
#include <IO/Operators.h>
#include <DataTypes/IDataType.h> #include <DataTypes/IDataType.h>
#include <DataTypes/DataTypeCustom.h> #include <DataTypes/DataTypeCustom.h>

View File

@ -115,7 +115,7 @@ void SerializationDynamic::serializeBinaryBulkStatePrefix(
dynamic_state->max_dynamic_types = column_dynamic.getMaxDynamicTypes(); dynamic_state->max_dynamic_types = column_dynamic.getMaxDynamicTypes();
/// Write max_dynamic_types parameter, because it can differ from the max_dynamic_types /// Write max_dynamic_types parameter, because it can differ from the max_dynamic_types
/// that is specified in the Dynamic type (we could decrease it before merge). /// that is specified in the Dynamic type (we could decrease it before merge).
writeBinaryLittleEndian(dynamic_state->max_dynamic_types, *stream); writeVarUInt(dynamic_state->max_dynamic_types, *stream);
dynamic_state->variant_type = variant_info.variant_type; dynamic_state->variant_type = variant_info.variant_type;
dynamic_state->variant_names = variant_info.variant_names; dynamic_state->variant_names = variant_info.variant_names;
@ -123,7 +123,7 @@ void SerializationDynamic::serializeBinaryBulkStatePrefix(
/// Write information about variants. /// Write information about variants.
size_t num_variants = dynamic_state->variant_names.size() - 1; /// Don't write shared variant, Dynamic column should always have it. size_t num_variants = dynamic_state->variant_names.size() - 1; /// Don't write shared variant, Dynamic column should always have it.
writeBinaryLittleEndian(num_variants, *stream); writeVarUInt(num_variants, *stream);
if (settings.data_types_binary_encoding) if (settings.data_types_binary_encoding)
{ {
const auto & variants = assert_cast<const DataTypeVariant &>(*dynamic_state->variant_type).getVariants(); const auto & variants = assert_cast<const DataTypeVariant &>(*dynamic_state->variant_type).getVariants();
@ -252,11 +252,11 @@ ISerialization::DeserializeBinaryBulkStatePtr SerializationDynamic::deserializeD
readBinaryLittleEndian(structure_version, *structure_stream); readBinaryLittleEndian(structure_version, *structure_stream);
auto structure_state = std::make_shared<DeserializeBinaryBulkStateDynamicStructure>(structure_version); auto structure_state = std::make_shared<DeserializeBinaryBulkStateDynamicStructure>(structure_version);
/// Read max_dynamic_types parameter. /// Read max_dynamic_types parameter.
readBinaryLittleEndian(structure_state->max_dynamic_types, *structure_stream); readVarUInt(structure_state->max_dynamic_types, *structure_stream);
/// Read information about variants. /// Read information about variants.
DataTypes variants; DataTypes variants;
size_t num_variants; size_t num_variants;
readBinaryLittleEndian(num_variants, *structure_stream); readVarUInt(num_variants, *structure_stream);
variants.reserve(num_variants + 1); /// +1 for shared variant. variants.reserve(num_variants + 1); /// +1 for shared variant.
if (settings.data_types_binary_encoding) if (settings.data_types_binary_encoding)
{ {

View File

@ -199,7 +199,7 @@ void SerializationObject::serializeBinaryBulkStatePrefix(
auto object_state = std::make_shared<SerializeBinaryBulkStateObject>(serialization_version); auto object_state = std::make_shared<SerializeBinaryBulkStateObject>(serialization_version);
object_state->max_dynamic_paths = column_object.getMaxDynamicPaths(); object_state->max_dynamic_paths = column_object.getMaxDynamicPaths();
/// Write max_dynamic_paths parameter. /// Write max_dynamic_paths parameter.
writeBinaryLittleEndian(object_state->max_dynamic_paths, *stream); writeVarUInt(object_state->max_dynamic_paths, *stream);
/// Write all dynamic paths in sorted order. /// Write all dynamic paths in sorted order.
object_state->sorted_dynamic_paths.reserve(dynamic_paths.size()); object_state->sorted_dynamic_paths.reserve(dynamic_paths.size());
for (const auto & [path, _] : dynamic_paths) for (const auto & [path, _] : dynamic_paths)
@ -354,7 +354,7 @@ ISerialization::DeserializeBinaryBulkStatePtr SerializationObject::deserializeOb
readBinaryLittleEndian(serialization_version, *structure_stream); readBinaryLittleEndian(serialization_version, *structure_stream);
auto structure_state = std::make_shared<DeserializeBinaryBulkStateObjectStructure>(serialization_version); auto structure_state = std::make_shared<DeserializeBinaryBulkStateObjectStructure>(serialization_version);
/// Read max_dynamic_paths parameter. /// Read max_dynamic_paths parameter.
readBinaryLittleEndian(structure_state->max_dynamic_paths, *structure_stream); readVarUInt(structure_state->max_dynamic_paths, *structure_stream);
/// Read the sorted list of dynamic paths. /// Read the sorted list of dynamic paths.
size_t dynamic_paths_size; size_t dynamic_paths_size;
readVarUInt(dynamic_paths_size, *structure_stream); readVarUInt(dynamic_paths_size, *structure_stream);

View File

@ -52,7 +52,7 @@ DatabaseLazy::DatabaseLazy(const String & name_, const String & metadata_path_,
void DatabaseLazy::loadStoredObjects(ContextMutablePtr local_context, LoadingStrictnessLevel /*mode*/) void DatabaseLazy::loadStoredObjects(ContextMutablePtr local_context, LoadingStrictnessLevel /*mode*/)
{ {
iterateMetadataFiles(local_context, [this, &local_context](const String & file_name) iterateMetadataFiles([this, &local_context](const String & file_name)
{ {
const std::string table_name = unescapeForFileName(file_name.substr(0, file_name.size() - 4)); const std::string table_name = unescapeForFileName(file_name.substr(0, file_name.size() - 4));

View File

@ -12,7 +12,7 @@ class DatabaseLazyIterator;
class Context; class Context;
/** Lazy engine of databases. /** Lazy engine of databases.
* Works like DatabaseOrdinary, but stores in memory only the cache. * Works like DatabaseOrdinary, but stores only recently accessed tables in memory.
* Can be used only with *Log engines. * Can be used only with *Log engines.
*/ */
class DatabaseLazy final : public DatabaseOnDisk class DatabaseLazy final : public DatabaseOnDisk

View File

@ -504,7 +504,7 @@ void DatabaseOnDisk::renameTable(
} }
/// It returns create table statement (even if table is detached) /// It returns the create table statement (even if table is detached)
ASTPtr DatabaseOnDisk::getCreateTableQueryImpl(const String & table_name, ContextPtr, bool throw_on_error) const ASTPtr DatabaseOnDisk::getCreateTableQueryImpl(const String & table_name, ContextPtr, bool throw_on_error) const
{ {
ASTPtr ast; ASTPtr ast;
@ -568,14 +568,14 @@ void DatabaseOnDisk::drop(ContextPtr local_context)
assert(TSA_SUPPRESS_WARNING_FOR_READ(tables).empty()); assert(TSA_SUPPRESS_WARNING_FOR_READ(tables).empty());
if (local_context->getSettingsRef().force_remove_data_recursively_on_drop) if (local_context->getSettingsRef().force_remove_data_recursively_on_drop)
{ {
(void)fs::remove_all(local_context->getPath() + getDataPath()); (void)fs::remove_all(std::filesystem::path(getContext()->getPath()) / data_path);
(void)fs::remove_all(getMetadataPath()); (void)fs::remove_all(getMetadataPath());
} }
else else
{ {
try try
{ {
(void)fs::remove(local_context->getPath() + getDataPath()); (void)fs::remove(std::filesystem::path(getContext()->getPath()) / data_path);
(void)fs::remove(getMetadataPath()); (void)fs::remove(getMetadataPath());
} }
catch (const fs::filesystem_error & e) catch (const fs::filesystem_error & e)
@ -613,7 +613,7 @@ time_t DatabaseOnDisk::getObjectMetadataModificationTime(const String & object_n
} }
} }
void DatabaseOnDisk::iterateMetadataFiles(ContextPtr local_context, const IteratingFunction & process_metadata_file) const void DatabaseOnDisk::iterateMetadataFiles(const IteratingFunction & process_metadata_file) const
{ {
auto process_tmp_drop_metadata_file = [&](const String & file_name) auto process_tmp_drop_metadata_file = [&](const String & file_name)
{ {
@ -621,7 +621,7 @@ void DatabaseOnDisk::iterateMetadataFiles(ContextPtr local_context, const Iterat
static const char * tmp_drop_ext = ".sql.tmp_drop"; static const char * tmp_drop_ext = ".sql.tmp_drop";
const std::string object_name = file_name.substr(0, file_name.size() - strlen(tmp_drop_ext)); const std::string object_name = file_name.substr(0, file_name.size() - strlen(tmp_drop_ext));
if (fs::exists(local_context->getPath() + getDataPath() + '/' + object_name)) if (fs::exists(std::filesystem::path(getContext()->getPath()) / data_path / object_name))
{ {
fs::rename(getMetadataPath() + file_name, getMetadataPath() + object_name + ".sql"); fs::rename(getMetadataPath() + file_name, getMetadataPath() + object_name + ".sql");
LOG_WARNING(log, "Object {} was not dropped previously and will be restored", backQuote(object_name)); LOG_WARNING(log, "Object {} was not dropped previously and will be restored", backQuote(object_name));
@ -638,7 +638,7 @@ void DatabaseOnDisk::iterateMetadataFiles(ContextPtr local_context, const Iterat
std::vector<std::pair<String, bool>> metadata_files; std::vector<std::pair<String, bool>> metadata_files;
fs::directory_iterator dir_end; fs::directory_iterator dir_end;
for (fs::directory_iterator dir_it(getMetadataPath()); dir_it != dir_end; ++dir_it) for (fs::directory_iterator dir_it(metadata_path); dir_it != dir_end; ++dir_it)
{ {
String file_name = dir_it->path().filename(); String file_name = dir_it->path().filename();
/// For '.svn', '.gitignore' directory and similar. /// For '.svn', '.gitignore' directory and similar.

View File

@ -64,7 +64,7 @@ public:
time_t getObjectMetadataModificationTime(const String & object_name) const override; time_t getObjectMetadataModificationTime(const String & object_name) const override;
String getDataPath() const override { return data_path; } String getDataPath() const override { return data_path; }
String getTableDataPath(const String & table_name) const override { return data_path + escapeForFileName(table_name) + "/"; } String getTableDataPath(const String & table_name) const override { return std::filesystem::path(data_path) / escapeForFileName(table_name) / ""; }
String getTableDataPath(const ASTCreateQuery & query) const override { return getTableDataPath(query.getTable()); } String getTableDataPath(const ASTCreateQuery & query) const override { return getTableDataPath(query.getTable()); }
String getMetadataPath() const override { return metadata_path; } String getMetadataPath() const override { return metadata_path; }
@ -83,7 +83,7 @@ protected:
using IteratingFunction = std::function<void(const String &)>; using IteratingFunction = std::function<void(const String &)>;
void iterateMetadataFiles(ContextPtr context, const IteratingFunction & process_metadata_file) const; void iterateMetadataFiles(const IteratingFunction & process_metadata_file) const;
ASTPtr getCreateTableQueryImpl( ASTPtr getCreateTableQueryImpl(
const String & table_name, const String & table_name,

View File

@ -55,7 +55,7 @@ static constexpr size_t METADATA_FILE_BUFFER_SIZE = 32768;
static constexpr const char * const CONVERT_TO_REPLICATED_FLAG_NAME = "convert_to_replicated"; static constexpr const char * const CONVERT_TO_REPLICATED_FLAG_NAME = "convert_to_replicated";
DatabaseOrdinary::DatabaseOrdinary(const String & name_, const String & metadata_path_, ContextPtr context_) DatabaseOrdinary::DatabaseOrdinary(const String & name_, const String & metadata_path_, ContextPtr context_)
: DatabaseOrdinary(name_, metadata_path_, "data/" + escapeForFileName(name_) + "/", "DatabaseOrdinary (" + name_ + ")", context_) : DatabaseOrdinary(name_, metadata_path_, std::filesystem::path("data") / escapeForFileName(name_) / "", "DatabaseOrdinary (" + name_ + ")", context_)
{ {
} }
@ -265,7 +265,7 @@ void DatabaseOrdinary::loadTablesMetadata(ContextPtr local_context, ParsedTables
} }
}; };
iterateMetadataFiles(local_context, process_metadata); iterateMetadataFiles(process_metadata);
size_t objects_in_database = metadata.parsed_tables.size() - prev_tables_count; size_t objects_in_database = metadata.parsed_tables.size() - prev_tables_count;
size_t dictionaries_in_database = metadata.total_dictionaries - prev_total_dictionaries; size_t dictionaries_in_database = metadata.total_dictionaries - prev_total_dictionaries;

View File

@ -21,6 +21,7 @@
#include <Databases/DatabaseReplicatedWorker.h> #include <Databases/DatabaseReplicatedWorker.h>
#include <Databases/DDLDependencyVisitor.h> #include <Databases/DDLDependencyVisitor.h>
#include <Databases/TablesDependencyGraph.h> #include <Databases/TablesDependencyGraph.h>
#include <Databases/enableAllExperimentalSettings.h>
#include <Interpreters/Cluster.h> #include <Interpreters/Cluster.h>
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <Interpreters/DatabaseCatalog.h> #include <Interpreters/DatabaseCatalog.h>
@ -1142,39 +1143,7 @@ void DatabaseReplicated::recoverLostReplica(const ZooKeeperPtr & current_zookeep
/// We will execute some CREATE queries for recovery (not ATTACH queries), /// We will execute some CREATE queries for recovery (not ATTACH queries),
/// so we need to allow experimental features that can be used in a CREATE query /// so we need to allow experimental features that can be used in a CREATE query
query_context->setSetting("allow_experimental_inverted_index", 1); enableAllExperimentalSettings(query_context);
query_context->setSetting("allow_experimental_full_text_index", 1);
query_context->setSetting("allow_experimental_codecs", 1);
query_context->setSetting("allow_experimental_live_view", 1);
query_context->setSetting("allow_experimental_window_view", 1);
query_context->setSetting("allow_experimental_funnel_functions", 1);
query_context->setSetting("allow_experimental_nlp_functions", 1);
query_context->setSetting("allow_experimental_hash_functions", 1);
query_context->setSetting("allow_experimental_object_type", 1);
query_context->setSetting("allow_experimental_variant_type", 1);
query_context->setSetting("allow_experimental_dynamic_type", 1);
query_context->setSetting("allow_experimental_json_type", 1);
query_context->setSetting("allow_experimental_vector_similarity_index", 1);
query_context->setSetting("allow_experimental_bigint_types", 1);
query_context->setSetting("allow_experimental_window_functions", 1);
query_context->setSetting("allow_experimental_geo_types", 1);
query_context->setSetting("allow_experimental_map_type", 1);
query_context->setSetting("allow_deprecated_error_prone_window_functions", 1);
query_context->setSetting("allow_suspicious_low_cardinality_types", 1);
query_context->setSetting("allow_suspicious_fixed_string_types", 1);
query_context->setSetting("allow_suspicious_indices", 1);
query_context->setSetting("allow_suspicious_codecs", 1);
query_context->setSetting("allow_hyperscan", 1);
query_context->setSetting("allow_simdjson", 1);
query_context->setSetting("allow_deprecated_syntax_for_merge_tree", 1);
query_context->setSetting("allow_suspicious_primary_key", 1);
query_context->setSetting("allow_suspicious_ttl_expressions", 1);
query_context->setSetting("allow_suspicious_variant_types", 1);
query_context->setSetting("enable_deflate_qpl_codec", 1);
query_context->setSetting("enable_zstd_qat_codec", 1);
query_context->setSetting("allow_create_index_without_type", 1);
query_context->setSetting("allow_experimental_s3queue", 1);
auto txn = std::make_shared<ZooKeeperMetadataTransaction>(current_zookeeper, zookeeper_path, false, ""); auto txn = std::make_shared<ZooKeeperMetadataTransaction>(current_zookeeper, zookeeper_path, false, "");
query_context->initZooKeeperMetadataTransaction(txn); query_context->initZooKeeperMetadataTransaction(txn);

View File

@ -14,6 +14,8 @@ namespace ErrorCodes
{ {
extern const int LOGICAL_ERROR; extern const int LOGICAL_ERROR;
extern const int CANNOT_GET_CREATE_TABLE_QUERY; extern const int CANNOT_GET_CREATE_TABLE_QUERY;
extern const int BAD_ARGUMENTS;
extern const int UNKNOWN_TABLE;
} }
DatabasesOverlay::DatabasesOverlay(const String & name_, ContextPtr context_) DatabasesOverlay::DatabasesOverlay(const String & name_, ContextPtr context_)
@ -124,6 +126,39 @@ StoragePtr DatabasesOverlay::detachTable(ContextPtr context_, const String & tab
getEngineName()); getEngineName());
} }
void DatabasesOverlay::renameTable(
ContextPtr current_context,
const String & name,
IDatabase & to_database,
const String & to_name,
bool exchange,
bool dictionary)
{
for (auto & db : databases)
{
if (db->isTableExist(name, current_context))
{
if (DatabasesOverlay * to_overlay_database = typeid_cast<DatabasesOverlay *>(&to_database))
{
/// Renaming from Overlay database inside itself or into another Overlay database.
/// Just use the first database in the overlay as a destination.
if (to_overlay_database->databases.empty())
throw Exception(ErrorCodes::BAD_ARGUMENTS, "The destination Overlay database {} does not have any members", to_database.getDatabaseName());
db->renameTable(current_context, name, *to_overlay_database->databases[0], to_name, exchange, dictionary);
}
else
{
/// Renaming into a different type of database. E.g. from Overlay on top of Atomic database into just Atomic database.
db->renameTable(current_context, name, to_database, to_name, exchange, dictionary);
}
return;
}
}
throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {}.{} doesn't exist", backQuote(getDatabaseName()), backQuote(name));
}
ASTPtr DatabasesOverlay::getCreateTableQueryImpl(const String & name, ContextPtr context_, bool throw_on_error) const ASTPtr DatabasesOverlay::getCreateTableQueryImpl(const String & name, ContextPtr context_, bool throw_on_error) const
{ {
ASTPtr result = nullptr; ASTPtr result = nullptr;
@ -178,6 +213,18 @@ String DatabasesOverlay::getTableDataPath(const ASTCreateQuery & query) const
return result; return result;
} }
UUID DatabasesOverlay::getUUID() const
{
UUID result = UUIDHelpers::Nil;
for (const auto & db : databases)
{
result = db->getUUID();
if (result != UUIDHelpers::Nil)
break;
}
return result;
}
UUID DatabasesOverlay::tryGetTableUUID(const String & table_name) const UUID DatabasesOverlay::tryGetTableUUID(const String & table_name) const
{ {
UUID result = UUIDHelpers::Nil; UUID result = UUIDHelpers::Nil;

View File

@ -35,12 +35,21 @@ public:
StoragePtr detachTable(ContextPtr context, const String & table_name) override; StoragePtr detachTable(ContextPtr context, const String & table_name) override;
void renameTable(
ContextPtr current_context,
const String & name,
IDatabase & to_database,
const String & to_name,
bool exchange,
bool dictionary) override;
ASTPtr getCreateTableQueryImpl(const String & name, ContextPtr context, bool throw_on_error) const override; ASTPtr getCreateTableQueryImpl(const String & name, ContextPtr context, bool throw_on_error) const override;
ASTPtr getCreateDatabaseQuery() const override; ASTPtr getCreateDatabaseQuery() const override;
String getTableDataPath(const String & table_name) const override; String getTableDataPath(const String & table_name) const override;
String getTableDataPath(const ASTCreateQuery & query) const override; String getTableDataPath(const ASTCreateQuery & query) const override;
UUID getUUID() const override;
UUID tryGetTableUUID(const String & table_name) const override; UUID tryGetTableUUID(const String & table_name) const override;
void drop(ContextPtr context) override; void drop(ContextPtr context) override;

View File

@ -0,0 +1,49 @@
#include <Interpreters/Context.h>
namespace DB
{
/*
* Enables all settings that allow the use of experimental, deprecated, or potentially unsafe features
* in a CREATE query. This function is used in DatabaseReplicated::recoverLostReplica() to create tables
* when the original settings used to create the table are not available.
*/
void enableAllExperimentalSettings(ContextMutablePtr context)
{
context->setSetting("allow_experimental_inverted_index", 1);
context->setSetting("allow_experimental_full_text_index", 1);
context->setSetting("allow_experimental_codecs", 1);
context->setSetting("allow_experimental_live_view", 1);
context->setSetting("allow_experimental_window_view", 1);
context->setSetting("allow_experimental_funnel_functions", 1);
context->setSetting("allow_experimental_nlp_functions", 1);
context->setSetting("allow_experimental_hash_functions", 1);
context->setSetting("allow_experimental_object_type", 1);
context->setSetting("allow_experimental_variant_type", 1);
context->setSetting("allow_experimental_dynamic_type", 1);
context->setSetting("allow_experimental_json_type", 1);
context->setSetting("allow_experimental_vector_similarity_index", 1);
context->setSetting("allow_experimental_bigint_types", 1);
context->setSetting("allow_experimental_window_functions", 1);
context->setSetting("allow_experimental_geo_types", 1);
context->setSetting("allow_experimental_map_type", 1);
context->setSetting("allow_deprecated_error_prone_window_functions", 1);
context->setSetting("allow_suspicious_low_cardinality_types", 1);
context->setSetting("allow_suspicious_fixed_string_types", 1);
context->setSetting("allow_suspicious_indices", 1);
context->setSetting("allow_suspicious_codecs", 1);
context->setSetting("allow_hyperscan", 1);
context->setSetting("allow_simdjson", 1);
context->setSetting("allow_deprecated_syntax_for_merge_tree", 1);
context->setSetting("allow_suspicious_primary_key", 1);
context->setSetting("allow_suspicious_ttl_expressions", 1);
context->setSetting("allow_suspicious_variant_types", 1);
context->setSetting("enable_deflate_qpl_codec", 1);
context->setSetting("enable_zstd_qat_codec", 1);
context->setSetting("allow_create_index_without_type", 1);
context->setSetting("allow_experimental_s3queue", 1);
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <Interpreters/Context_fwd.h>
namespace DB
{
/*
* Enables all settings that allow the use of experimental, deprecated, or potentially unsafe features
* in a CREATE query. This function is used in DatabaseReplicated::recoverLostReplica() to create tables
* when the original settings used to create the table are not available.
*/
void enableAllExperimentalSettings(ContextMutablePtr context);
}

View File

@ -8,12 +8,12 @@
#include <IO/WriteHelpers.h> #include <IO/WriteHelpers.h>
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <Processors/Formats/IInputFormat.h> #include <Processors/Formats/IInputFormat.h>
#include <Storages/ExternalDataSourceConfiguration.h>
#include <Poco/Net/HTTPRequest.h> #include <Poco/Net/HTTPRequest.h>
#include <Common/logger_useful.h> #include <Common/logger_useful.h>
#include "DictionarySourceFactory.h" #include "DictionarySourceFactory.h"
#include "DictionarySourceHelpers.h" #include "DictionarySourceHelpers.h"
#include "DictionaryStructure.h" #include "DictionaryStructure.h"
#include <Storages/NamedCollectionsHelpers.h>
#include "registerDictionaries.h" #include "registerDictionaries.h"
@ -223,21 +223,23 @@ void registerDictionarySourceHTTP(DictionarySourceFactory & factory)
String endpoint; String endpoint;
String format; String format;
auto named_collection = created_from_ddl auto named_collection = created_from_ddl ? tryGetNamedCollectionWithOverrides(config, settings_config_prefix, global_context) : nullptr;
? getURLBasedDataSourceConfiguration(config, settings_config_prefix, global_context)
: std::nullopt;
if (named_collection) if (named_collection)
{ {
url = named_collection->configuration.url; validateNamedCollection(
endpoint = named_collection->configuration.endpoint; *named_collection,
format = named_collection->configuration.format; /* required_keys */{},
/* optional_keys */ValidateKeysMultiset<ExternalDatabaseEqualKeysSet>{
"url", "endpoint", "user", "credentials.user", "password", "credentials.password", "format", "compression_method", "structure", "name"});
credentials.setUsername(named_collection->configuration.user); url = named_collection->getOrDefault<String>("url", "");
credentials.setPassword(named_collection->configuration.password); endpoint = named_collection->getOrDefault<String>("endpoint", "");
format = named_collection->getOrDefault<String>("format", "");
header_entries.reserve(named_collection->configuration.headers.size()); credentials.setUsername(named_collection->getAnyOrDefault<String>({"user", "credentials.user"}, ""));
for (const auto & [key, value] : named_collection->configuration.headers) credentials.setPassword(named_collection->getAnyOrDefault<String>({"password", "credentials.password"}, ""));
header_entries.emplace_back(key, value);
header_entries = getHeadersFromNamedCollection(*named_collection);
} }
else else
{ {

View File

@ -1,15 +1,12 @@
#include "MongoDBDictionarySource.h" #include "MongoDBDictionarySource.h"
#include "DictionarySourceFactory.h" #include "DictionarySourceFactory.h"
#include "DictionaryStructure.h" #include "DictionaryStructure.h"
#include <Storages/ExternalDataSourceConfiguration.h>
#include <Storages/StorageMongoDBSocketFactory.h> #include <Storages/StorageMongoDBSocketFactory.h>
#include <Storages/NamedCollectionsHelpers.h>
namespace DB namespace DB
{ {
static const std::unordered_set<std::string_view> dictionary_allowed_keys = {
"host", "port", "user", "password", "db", "database", "uri", "collection", "name", "method", "options"};
void registerDictionarySourceMongoDB(DictionarySourceFactory & factory) void registerDictionarySourceMongoDB(DictionarySourceFactory & factory)
{ {
auto create_mongo_db_dictionary = []( auto create_mongo_db_dictionary = [](
@ -22,35 +19,53 @@ void registerDictionarySourceMongoDB(DictionarySourceFactory & factory)
bool created_from_ddl) bool created_from_ddl)
{ {
const auto config_prefix = root_config_prefix + ".mongodb"; const auto config_prefix = root_config_prefix + ".mongodb";
ExternalDataSourceConfiguration configuration; auto named_collection = created_from_ddl ? tryGetNamedCollectionWithOverrides(config, config_prefix, context) : nullptr;
auto has_config_key = [](const String & key) { return dictionary_allowed_keys.contains(key); };
auto named_collection = getExternalDataSourceConfiguration(config, config_prefix, context, has_config_key); String host, username, password, database, method, options, collection;
UInt16 port;
if (named_collection) if (named_collection)
{ {
configuration = named_collection->configuration; validateNamedCollection(
*named_collection,
/* required_keys */{"collection"},
/* optional_keys */ValidateKeysMultiset<ExternalDatabaseEqualKeysSet>{
"host", "port", "user", "password", "db", "database", "uri", "name", "method", "options"});
host = named_collection->getOrDefault<String>("host", "");
port = static_cast<UInt16>(named_collection->getOrDefault<UInt64>("port", 0));
username = named_collection->getOrDefault<String>("user", "");
password = named_collection->getOrDefault<String>("password", "");
database = named_collection->getAnyOrDefault<String>({"db", "database"}, "");
method = named_collection->getOrDefault<String>("method", "");
collection = named_collection->getOrDefault<String>("collection", "");
options = named_collection->getOrDefault<String>("options", "");
} }
else else
{ {
configuration.host = config.getString(config_prefix + ".host", ""); host = config.getString(config_prefix + ".host", "");
configuration.port = config.getUInt(config_prefix + ".port", 0); port = config.getUInt(config_prefix + ".port", 0);
configuration.username = config.getString(config_prefix + ".user", ""); username = config.getString(config_prefix + ".user", "");
configuration.password = config.getString(config_prefix + ".password", ""); password = config.getString(config_prefix + ".password", "");
configuration.database = config.getString(config_prefix + ".db", ""); database = config.getString(config_prefix + ".db", "");
method = config.getString(config_prefix + ".method", "");
collection = config.getString(config_prefix + ".collection");
options = config.getString(config_prefix + ".options", "");
} }
if (created_from_ddl) if (created_from_ddl)
context->getRemoteHostFilter().checkHostAndPort(configuration.host, toString(configuration.port)); context->getRemoteHostFilter().checkHostAndPort(host, toString(port));
return std::make_unique<MongoDBDictionarySource>(dict_struct, return std::make_unique<MongoDBDictionarySource>(
dict_struct,
config.getString(config_prefix + ".uri", ""), config.getString(config_prefix + ".uri", ""),
configuration.host, host,
configuration.port, port,
configuration.username, username,
configuration.password, password,
config.getString(config_prefix + ".method", ""), method,
configuration.database, database,
config.getString(config_prefix + ".collection"), collection,
config.getString(config_prefix + ".options", ""), options,
sample_block); sample_block);
}; };

View File

@ -4,6 +4,7 @@
#include <Core/QualifiedTableName.h> #include <Core/QualifiedTableName.h>
#include <Core/Settings.h> #include <Core/Settings.h>
#include "DictionarySourceFactory.h" #include "DictionarySourceFactory.h"
#include <Storages/NamedCollectionsHelpers.h>
#include "registerDictionaries.h" #include "registerDictionaries.h"
#if USE_LIBPQXX #if USE_LIBPQXX
@ -13,7 +14,6 @@
#include "readInvalidateQuery.h" #include "readInvalidateQuery.h"
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <QueryPipeline/QueryPipeline.h> #include <QueryPipeline/QueryPipeline.h>
#include <Storages/ExternalDataSourceConfiguration.h>
#include <Common/logger_useful.h> #include <Common/logger_useful.h>
#endif #endif
@ -24,16 +24,17 @@ namespace DB
namespace ErrorCodes namespace ErrorCodes
{ {
extern const int SUPPORT_IS_DISABLED; extern const int SUPPORT_IS_DISABLED;
extern const int BAD_ARGUMENTS;
} }
static const ValidateKeysMultiset<ExternalDatabaseEqualKeysSet> dictionary_allowed_keys = {
"host", "port", "user", "password", "db", "database", "table", "schema",
"update_field", "update_lag", "invalidate_query", "query", "where", "name", "priority"};
#if USE_LIBPQXX #if USE_LIBPQXX
static const UInt64 max_block_size = 8192; static const UInt64 max_block_size = 8192;
static const std::unordered_set<std::string_view> dictionary_allowed_keys = {
"host", "port", "user", "password", "db", "database", "table", "schema",
"update_field", "update_lag", "invalidate_query", "query", "where", "name", "priority"};
namespace namespace
{ {
ExternalQueryBuilder makeExternalQueryBuilder(const DictionaryStructure & dict_struct, const String & schema, const String & table, const String & query, const String & where) ExternalQueryBuilder makeExternalQueryBuilder(const DictionaryStructure & dict_struct, const String & schema, const String & table, const String & query, const String & where)
@ -177,6 +178,19 @@ std::string PostgreSQLDictionarySource::toString() const
return "PostgreSQL: " + configuration.db + '.' + configuration.table + (where.empty() ? "" : ", where: " + where); return "PostgreSQL: " + configuration.db + '.' + configuration.table + (where.empty() ? "" : ", where: " + where);
} }
static void validateConfigKeys(
const Poco::Util::AbstractConfiguration & dict_config, const String & config_prefix)
{
Poco::Util::AbstractConfiguration::Keys config_keys;
dict_config.keys(config_prefix, config_keys);
for (const auto & config_key : config_keys)
{
if (dictionary_allowed_keys.contains(config_key) || startsWith(config_key, "replica"))
continue;
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unexpected key `{}` in dictionary source configuration", config_key);
}
}
#endif #endif
void registerDictionarySourcePostgreSQL(DictionarySourceFactory & factory) void registerDictionarySourcePostgreSQL(DictionarySourceFactory & factory)
@ -191,38 +205,117 @@ void registerDictionarySourcePostgreSQL(DictionarySourceFactory & factory)
{ {
#if USE_LIBPQXX #if USE_LIBPQXX
const auto settings_config_prefix = config_prefix + ".postgresql"; const auto settings_config_prefix = config_prefix + ".postgresql";
auto has_config_key = [](const String & key) { return dictionary_allowed_keys.contains(key) || key.starts_with("replica"); };
auto configuration = getExternalDataSourceConfigurationByPriority(config, settings_config_prefix, context, has_config_key);
const auto & settings = context->getSettingsRef(); const auto & settings = context->getSettingsRef();
std::optional<PostgreSQLDictionarySource::Configuration> dictionary_configuration;
postgres::PoolWithFailover::ReplicasConfigurationByPriority replicas_by_priority;
auto named_collection = created_from_ddl ? tryGetNamedCollectionWithOverrides(config, settings_config_prefix, context) : nullptr;
if (named_collection)
{
validateNamedCollection<ValidateKeysMultiset<ExternalDatabaseEqualKeysSet>>(*named_collection, {}, dictionary_allowed_keys);
StoragePostgreSQL::Configuration common_configuration;
common_configuration.host = named_collection->getOrDefault<String>("host", "");
common_configuration.port = named_collection->getOrDefault<UInt64>("port", 0);
common_configuration.username = named_collection->getOrDefault<String>("user", "");
common_configuration.password = named_collection->getOrDefault<String>("password", "");
common_configuration.database = named_collection->getAnyOrDefault<String>({"database", "db"}, "");
common_configuration.schema = named_collection->getOrDefault<String>("schema", "");
common_configuration.table = named_collection->getOrDefault<String>("table", "");
dictionary_configuration.emplace(PostgreSQLDictionarySource::Configuration{
.db = common_configuration.database,
.schema = common_configuration.schema,
.table = common_configuration.table,
.query = named_collection->getOrDefault<String>("query", ""),
.where = named_collection->getOrDefault<String>("where", ""),
.invalidate_query = named_collection->getOrDefault<String>("invalidate_query", ""),
.update_field = named_collection->getOrDefault<String>("update_field", ""),
.update_lag = named_collection->getOrDefault<UInt64>("update_lag", 1),
});
replicas_by_priority[0].emplace_back(common_configuration);
}
else
{
validateConfigKeys(config, settings_config_prefix);
StoragePostgreSQL::Configuration common_configuration;
common_configuration.host = config.getString(settings_config_prefix + ".host", "");
common_configuration.port = config.getUInt(settings_config_prefix + ".port", 0);
common_configuration.username = config.getString(settings_config_prefix + ".user", "");
common_configuration.password = config.getString(settings_config_prefix + ".password", "");
common_configuration.database = config.getString(fmt::format("{}.database", settings_config_prefix), config.getString(fmt::format("{}.db", settings_config_prefix), ""));
common_configuration.schema = config.getString(fmt::format("{}.schema", settings_config_prefix), "");
common_configuration.table = config.getString(fmt::format("{}.table", settings_config_prefix), "");
dictionary_configuration.emplace(PostgreSQLDictionarySource::Configuration
{
.db = common_configuration.database,
.schema = common_configuration.schema,
.table = common_configuration.table,
.query = config.getString(fmt::format("{}.query", settings_config_prefix), ""),
.where = config.getString(fmt::format("{}.where", settings_config_prefix), ""),
.invalidate_query = config.getString(fmt::format("{}.invalidate_query", settings_config_prefix), ""),
.update_field = config.getString(fmt::format("{}.update_field", settings_config_prefix), ""),
.update_lag = config.getUInt64(fmt::format("{}.update_lag", settings_config_prefix), 1)
});
if (config.has(settings_config_prefix + ".replica"))
{
Poco::Util::AbstractConfiguration::Keys config_keys;
config.keys(settings_config_prefix, config_keys);
for (const auto & config_key : config_keys)
{
if (config_key.starts_with("replica"))
{
String replica_name = settings_config_prefix + "." + config_key;
StoragePostgreSQL::Configuration replica_configuration{common_configuration};
size_t priority = config.getInt(replica_name + ".priority", 0);
replica_configuration.host = config.getString(replica_name + ".host", common_configuration.host);
replica_configuration.port = config.getUInt(replica_name + ".port", common_configuration.port);
replica_configuration.username = config.getString(replica_name + ".user", common_configuration.username);
replica_configuration.password = config.getString(replica_name + ".password", common_configuration.password);
if (replica_configuration.host.empty() || replica_configuration.port == 0
|| replica_configuration.username.empty() || replica_configuration.password.empty())
{
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"Named collection of connection parameters is missing some "
"of the parameters and no other dictionary parameters are added");
}
replicas_by_priority[priority].emplace_back(replica_configuration);
}
}
}
else
{
replicas_by_priority[0].emplace_back(common_configuration);
}
}
if (created_from_ddl) if (created_from_ddl)
{ {
for (const auto & replicas : configuration.replicas_configurations) for (const auto & [_, replicas] : replicas_by_priority)
for (const auto & replica : replicas.second) for (const auto & replica : replicas)
context->getRemoteHostFilter().checkHostAndPort(replica.host, toString(replica.port)); context->getRemoteHostFilter().checkHostAndPort(replica.host, toString(replica.port));
} }
auto pool = std::make_shared<postgres::PoolWithFailover>( auto pool = std::make_shared<postgres::PoolWithFailover>(
configuration.replicas_configurations, replicas_by_priority,
settings.postgresql_connection_pool_size, settings.postgresql_connection_pool_size,
settings.postgresql_connection_pool_wait_timeout, settings.postgresql_connection_pool_wait_timeout,
settings.postgresql_connection_pool_retries, settings.postgresql_connection_pool_retries,
settings.postgresql_connection_pool_auto_close_connection, settings.postgresql_connection_pool_auto_close_connection,
settings.postgresql_connection_attempt_timeout); settings.postgresql_connection_attempt_timeout);
PostgreSQLDictionarySource::Configuration dictionary_configuration
{
.db = configuration.database,
.schema = configuration.schema,
.table = configuration.table,
.query = config.getString(fmt::format("{}.query", settings_config_prefix), ""),
.where = config.getString(fmt::format("{}.where", settings_config_prefix), ""),
.invalidate_query = config.getString(fmt::format("{}.invalidate_query", settings_config_prefix), ""),
.update_field = config.getString(fmt::format("{}.update_field", settings_config_prefix), ""),
.update_lag = config.getUInt64(fmt::format("{}.update_lag", settings_config_prefix), 1)
};
return std::make_unique<PostgreSQLDictionarySource>(dict_struct, dictionary_configuration, pool, sample_block); return std::make_unique<PostgreSQLDictionarySource>(dict_struct, dictionary_configuration.value(), pool, sample_block);
#else #else
(void)dict_struct; (void)dict_struct;
(void)config; (void)config;

View File

@ -80,20 +80,27 @@ SeekableReadBufferPtr ReadBufferFromRemoteFSGather::createImplementationBuffer(c
if (with_file_cache) if (with_file_cache)
{ {
auto cache_key = settings.remote_fs_cache->createKeyForPath(object_path); if (settings.remote_fs_cache->isInitialized())
buf = std::make_unique<CachedOnDiskReadBufferFromFile>( {
object_path, auto cache_key = settings.remote_fs_cache->createKeyForPath(object_path);
cache_key, buf = std::make_unique<CachedOnDiskReadBufferFromFile>(
settings.remote_fs_cache, object_path,
FileCache::getCommonUser(), cache_key,
[=, this]() { return read_buffer_creator(/* restricted_seek */true, object); }, settings.remote_fs_cache,
settings, FileCache::getCommonUser(),
query_id, [=, this]() { return read_buffer_creator(/* restricted_seek */true, object); },
object.bytes_size, settings,
/* allow_seeks */false, query_id,
/* use_external_buffer */true, object.bytes_size,
/* read_until_position */std::nullopt, /* allow_seeks */false,
cache_log); /* use_external_buffer */true,
/* read_until_position */std::nullopt,
cache_log);
}
else
{
settings.remote_fs_cache->throwInitExceptionIfNeeded();
}
} }
/// Can't wrap CachedOnDiskReadBufferFromFile in CachedInMemoryReadBufferFromFile because the /// Can't wrap CachedOnDiskReadBufferFromFile in CachedInMemoryReadBufferFromFile because the

View File

@ -99,7 +99,7 @@ std::unique_ptr<WriteBufferFromFileBase> CachedObjectStorage::writeObject( /// N
/// Need to remove even if cache_on_write == false. /// Need to remove even if cache_on_write == false.
removeCacheIfExists(object.remote_path); removeCacheIfExists(object.remote_path);
if (cache_on_write) if (cache_on_write && cache->isInitialized())
{ {
auto key = getCacheKey(object.remote_path); auto key = getCacheKey(object.remote_path);
return std::make_unique<CachedOnDiskWriteBufferFromFile>( return std::make_unique<CachedOnDiskWriteBufferFromFile>(
@ -122,7 +122,8 @@ void CachedObjectStorage::removeCacheIfExists(const std::string & path_key_for_c
return; return;
/// Add try catch? /// Add try catch?
cache->removeKeyIfExists(getCacheKey(path_key_for_cache), FileCache::getCommonUser().user_id); if (cache->isInitialized())
cache->removeKeyIfExists(getCacheKey(path_key_for_cache), FileCache::getCommonUser().user_id);
} }
void CachedObjectStorage::removeObject(const StoredObject & object) void CachedObjectStorage::removeObject(const StoredObject & object)

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <Columns/ColumnString.h> #include <Columns/ColumnString.h>
namespace DB namespace DB
{ {

View File

@ -1,15 +1,14 @@
#pragma once #pragma once
#include "config.h"
#if USE_ICU
#include <Columns/ColumnString.h> #include <Columns/ColumnString.h>
#include <Functions/LowerUpperImpl.h> #include <Functions/LowerUpperImpl.h>
#include <base/defines.h> #include <base/find_symbols.h>
#include <Poco/UTF8Encoding.h> #include <unicode/unistr.h>
#include <Common/StringUtils.h> #include <Common/StringUtils.h>
#include <Common/UTF8Helpers.h>
#ifdef __SSE2__
#include <emmintrin.h>
#endif
namespace DB namespace DB
{ {
@ -19,71 +18,7 @@ namespace ErrorCodes
extern const int BAD_ARGUMENTS; extern const int BAD_ARGUMENTS;
} }
/// xor or do nothing template <char not_case_lower_bound, char not_case_upper_bound, bool upper>
template <bool>
UInt8 xor_or_identity(const UInt8 c, const int mask)
{
return c ^ mask;
}
template <>
inline UInt8 xor_or_identity<false>(const UInt8 c, const int)
{
return c;
}
/// It is caller's responsibility to ensure the presence of a valid cyrillic sequence in array
template <bool to_lower>
inline void UTF8CyrillicToCase(const UInt8 *& src, UInt8 *& dst)
{
if (src[0] == 0xD0u && (src[1] >= 0x80u && src[1] <= 0x8Fu))
{
/// ЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏ
*dst++ = xor_or_identity<to_lower>(*src++, 0x1);
*dst++ = xor_or_identity<to_lower>(*src++, 0x10);
}
else if (src[0] == 0xD1u && (src[1] >= 0x90u && src[1] <= 0x9Fu))
{
/// ѐёђѓєѕіїјљњћќѝўџ
*dst++ = xor_or_identity<!to_lower>(*src++, 0x1);
*dst++ = xor_or_identity<!to_lower>(*src++, 0x10);
}
else if (src[0] == 0xD0u && (src[1] >= 0x90u && src[1] <= 0x9Fu))
{
/// А
*dst++ = *src++;
*dst++ = xor_or_identity<to_lower>(*src++, 0x20);
}
else if (src[0] == 0xD0u && (src[1] >= 0xB0u && src[1] <= 0xBFu))
{
/// а-п
*dst++ = *src++;
*dst++ = xor_or_identity<!to_lower>(*src++, 0x20);
}
else if (src[0] == 0xD0u && (src[1] >= 0xA0u && src[1] <= 0xAFu))
{
/// Р
*dst++ = xor_or_identity<to_lower>(*src++, 0x1);
*dst++ = xor_or_identity<to_lower>(*src++, 0x20);
}
else if (src[0] == 0xD1u && (src[1] >= 0x80u && src[1] <= 0x8Fu))
{
/// р
*dst++ = xor_or_identity<!to_lower>(*src++, 0x1);
*dst++ = xor_or_identity<!to_lower>(*src++, 0x20);
}
}
/** If the string contains UTF-8 encoded text, convert it to the lower (upper) case.
* Note: It is assumed that after the character is converted to another case,
* the length of its multibyte sequence in UTF-8 does not change.
* Otherwise, the behavior is undefined.
*/
template <char not_case_lower_bound,
char not_case_upper_bound,
int to_case(int),
void cyrillic_to_case(const UInt8 *&, UInt8 *&)>
struct LowerUpperUTF8Impl struct LowerUpperUTF8Impl
{ {
static void vector( static void vector(
@ -103,180 +38,46 @@ struct LowerUpperUTF8Impl
return; return;
} }
res_data.resize_exact(data.size()); res_data.resize(data.size());
res_offsets.assign(offsets); res_offsets.resize_exact(offsets.size());
array(data.data(), data.data() + data.size(), offsets, res_data.data());
String output;
size_t curr_offset = 0;
for (size_t i = 0; i < offsets.size(); ++i)
{
const auto * data_start = reinterpret_cast<const char *>(&data[offsets[i - 1]]);
size_t size = offsets[i] - offsets[i - 1];
icu::UnicodeString input(data_start, static_cast<int32_t>(size), "UTF-8");
if constexpr (upper)
input.toUpper();
else
input.toLower();
output.clear();
input.toUTF8String(output);
/// For valid UTF-8 input strings, ICU sometimes produces output with extra '\0's at the end. Only the data before the first
/// '\0' is valid. It the input is not valid UTF-8, then the behavior of lower/upperUTF8 is undefined by definition. In this
/// case, the behavior is also reasonable.
const char * res_end = find_last_not_symbols_or_null<'\0'>(output.data(), output.data() + output.size());
size_t valid_size = res_end ? res_end - output.data() + 1 : 0;
res_data.resize(curr_offset + valid_size + 1);
memcpy(&res_data[curr_offset], output.data(), valid_size);
res_data[curr_offset + valid_size] = 0;
curr_offset += valid_size + 1;
res_offsets[i] = curr_offset;
}
} }
static void vectorFixed(const ColumnString::Chars &, size_t, ColumnString::Chars &, size_t) static void vectorFixed(const ColumnString::Chars &, size_t, ColumnString::Chars &, size_t)
{ {
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Functions lowerUTF8 and upperUTF8 cannot work with FixedString argument"); throw Exception(ErrorCodes::BAD_ARGUMENTS, "Functions lowerUTF8 and upperUTF8 cannot work with FixedString argument");
} }
/** Converts a single code point starting at `src` to desired case, storing result starting at `dst`.
* `src` and `dst` are incremented by corresponding sequence lengths. */
static bool toCase(const UInt8 *& src, const UInt8 * src_end, UInt8 *& dst, bool partial)
{
if (src[0] <= ascii_upper_bound)
{
if (*src >= not_case_lower_bound && *src <= not_case_upper_bound)
*dst++ = *src++ ^ flip_case_mask;
else
*dst++ = *src++;
}
else if (src + 1 < src_end
&& ((src[0] == 0xD0u && (src[1] >= 0x80u && src[1] <= 0xBFu)) || (src[0] == 0xD1u && (src[1] >= 0x80u && src[1] <= 0x9Fu))))
{
cyrillic_to_case(src, dst);
}
else if (src + 1 < src_end && src[0] == 0xC2u)
{
/// Punctuation U+0080 - U+00BF, UTF-8: C2 80 - C2 BF
*dst++ = *src++;
*dst++ = *src++;
}
else if (src + 2 < src_end && src[0] == 0xE2u)
{
/// Characters U+2000 - U+2FFF, UTF-8: E2 80 80 - E2 BF BF
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
else
{
size_t src_sequence_length = UTF8::seqLength(*src);
/// In case partial buffer was passed (due to SSE optimization)
/// we cannot convert it with current src_end, but we may have more
/// bytes to convert and eventually got correct symbol.
if (partial && src_sequence_length > static_cast<size_t>(src_end - src))
return false;
auto src_code_point = UTF8::convertUTF8ToCodePoint(src, src_end - src);
if (src_code_point)
{
int dst_code_point = to_case(*src_code_point);
if (dst_code_point > 0)
{
size_t dst_sequence_length = UTF8::convertCodePointToUTF8(dst_code_point, dst, src_end - src);
assert(dst_sequence_length <= 4);
/// We don't support cases when lowercase and uppercase characters occupy different number of bytes in UTF-8.
/// As an example, this happens for ß and ẞ.
if (dst_sequence_length == src_sequence_length)
{
src += dst_sequence_length;
dst += dst_sequence_length;
return true;
}
}
}
*dst = *src;
++dst;
++src;
}
return true;
}
private:
static constexpr auto ascii_upper_bound = '\x7f';
static constexpr auto flip_case_mask = 'A' ^ 'a';
static void array(const UInt8 * src, const UInt8 * src_end, const ColumnString::Offsets & offsets, UInt8 * dst)
{
const auto * offset_it = offsets.begin();
const UInt8 * begin = src;
#ifdef __SSE2__
static constexpr auto bytes_sse = sizeof(__m128i);
/// If we are before this position, we can still read at least bytes_sse.
const auto * src_end_sse = src_end - bytes_sse + 1;
/// SSE2 packed comparison operate on signed types, hence compare (c < 0) instead of (c > 0x7f)
const auto v_zero = _mm_setzero_si128();
const auto v_not_case_lower_bound = _mm_set1_epi8(not_case_lower_bound - 1);
const auto v_not_case_upper_bound = _mm_set1_epi8(not_case_upper_bound + 1);
const auto v_flip_case_mask = _mm_set1_epi8(flip_case_mask);
while (src < src_end_sse)
{
const auto chars = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src));
/// check for ASCII
const auto is_not_ascii = _mm_cmplt_epi8(chars, v_zero);
const auto mask_is_not_ascii = _mm_movemask_epi8(is_not_ascii);
/// ASCII
if (mask_is_not_ascii == 0)
{
const auto is_not_case
= _mm_and_si128(_mm_cmpgt_epi8(chars, v_not_case_lower_bound), _mm_cmplt_epi8(chars, v_not_case_upper_bound));
const auto mask_is_not_case = _mm_movemask_epi8(is_not_case);
/// everything in correct case ASCII
if (mask_is_not_case == 0)
_mm_storeu_si128(reinterpret_cast<__m128i *>(dst), chars);
else
{
/// ASCII in mixed case
/// keep `flip_case_mask` only where necessary, zero out elsewhere
const auto xor_mask = _mm_and_si128(v_flip_case_mask, is_not_case);
/// flip case by applying calculated mask
const auto cased_chars = _mm_xor_si128(chars, xor_mask);
/// store result back to destination
_mm_storeu_si128(reinterpret_cast<__m128i *>(dst), cased_chars);
}
src += bytes_sse;
dst += bytes_sse;
}
else
{
/// UTF-8
/// Find the offset of the next string after src
size_t offset_from_begin = src - begin;
while (offset_from_begin >= *offset_it)
++offset_it;
/// Do not allow one row influence another (since row may have invalid sequence, and break the next)
const UInt8 * row_end = begin + *offset_it;
chassert(row_end >= src);
const UInt8 * expected_end = std::min(src + bytes_sse, row_end);
while (src < expected_end)
{
if (!toCase(src, expected_end, dst, /* partial= */ true))
{
/// Fallback to handling byte by byte.
src_end_sse = src;
break;
}
}
}
}
/// Find the offset of the next string after src
size_t offset_from_begin = src - begin;
while (offset_it != offsets.end() && offset_from_begin >= *offset_it)
++offset_it;
#endif
/// handle remaining symbols, row by row (to avoid influence of bad UTF8 symbols from one row, to another)
while (src < src_end)
{
const UInt8 * row_end = begin + *offset_it;
chassert(row_end >= src);
while (src < row_end)
toCase(src, row_end, dst, /* partial= */ false);
++offset_it;
}
}
}; };
} }
#endif

View File

@ -43,6 +43,7 @@ public:
max_query_size = settings.max_query_size; max_query_size = settings.max_query_size;
max_parser_depth = settings.max_parser_depth; max_parser_depth = settings.max_parser_depth;
max_parser_backtracks = settings.max_parser_backtracks; max_parser_backtracks = settings.max_parser_backtracks;
print_pretty_type_names = settings.print_pretty_type_names;
} }
String getName() const override { return name; } String getName() const override { return name; }
@ -138,7 +139,11 @@ private:
} }
} }
formatAST(*ast, buf, /*hilite*/ false, /*single_line*/ output_formatting == OutputFormatting::SingleLine); IAST::FormatSettings settings(buf, output_formatting == OutputFormatting::SingleLine, /*hilite*/ false);
settings.show_secrets = true;
settings.print_pretty_type_names = print_pretty_type_names;
ast->format(settings);
auto formatted = buf.stringView(); auto formatted = buf.stringView();
const size_t res_data_new_size = res_data_size + formatted.size() + 1; const size_t res_data_new_size = res_data_size + formatted.size() + 1;
@ -165,6 +170,7 @@ private:
size_t max_query_size; size_t max_query_size;
size_t max_parser_depth; size_t max_parser_depth;
size_t max_parser_backtracks; size_t max_parser_backtracks;
bool print_pretty_type_names;
}; };
} }

View File

@ -1,9 +1,8 @@
#include <DataTypes/DataTypeString.h> #include <DataTypes/DataTypeString.h>
#include <Functions/FunctionStringToString.h> #include <Functions/FunctionStringToString.h>
#include <Functions/LowerUpperUTF8Impl.h>
#include <Functions/FunctionFactory.h> #include <Functions/FunctionFactory.h>
#include <Poco/Unicode.h> #include <Poco/Unicode.h>
#include <Common/UTF8Helpers.h>
namespace DB namespace DB
{ {

View File

@ -1,9 +1,10 @@
#include <DataTypes/DataTypeString.h> #include "config.h"
#if USE_ICU
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionStringToString.h> #include <Functions/FunctionStringToString.h>
#include <Functions/LowerUpperUTF8Impl.h> #include <Functions/LowerUpperUTF8Impl.h>
#include <Functions/FunctionFactory.h>
#include <Poco/Unicode.h>
namespace DB namespace DB
{ {
@ -15,13 +16,25 @@ struct NameLowerUTF8
static constexpr auto name = "lowerUTF8"; static constexpr auto name = "lowerUTF8";
}; };
using FunctionLowerUTF8 = FunctionStringToString<LowerUpperUTF8Impl<'A', 'Z', Poco::Unicode::toLower, UTF8CyrillicToCase<true>>, NameLowerUTF8>; using FunctionLowerUTF8 = FunctionStringToString<LowerUpperUTF8Impl<'A', 'Z', false>, NameLowerUTF8>;
} }
REGISTER_FUNCTION(LowerUTF8) REGISTER_FUNCTION(LowerUTF8)
{ {
factory.registerFunction<FunctionLowerUTF8>(); FunctionDocumentation::Description description
= R"(Converts a string to lowercase, assuming that the string contains valid UTF-8 encoded text. If this assumption is violated, no exception is thrown and the result is undefined.)";
FunctionDocumentation::Syntax syntax = "lowerUTF8(input)";
FunctionDocumentation::Arguments arguments = {{"input", "Input with String type"}};
FunctionDocumentation::ReturnedValue returned_value = "A String data type value";
FunctionDocumentation::Examples examples = {
{"first", "SELECT lowerUTF8('München') as Lowerutf8;", "münchen"},
};
FunctionDocumentation::Categories categories = {"String"};
factory.registerFunction<FunctionLowerUTF8>({description, syntax, arguments, returned_value, examples, categories});
} }
} }
#endif

View File

@ -1,8 +1,10 @@
#include "config.h"
#if USE_ICU
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionStringToString.h> #include <Functions/FunctionStringToString.h>
#include <Functions/LowerUpperUTF8Impl.h> #include <Functions/LowerUpperUTF8Impl.h>
#include <Functions/FunctionFactory.h>
#include <Poco/Unicode.h>
namespace DB namespace DB
{ {
@ -14,13 +16,25 @@ struct NameUpperUTF8
static constexpr auto name = "upperUTF8"; static constexpr auto name = "upperUTF8";
}; };
using FunctionUpperUTF8 = FunctionStringToString<LowerUpperUTF8Impl<'a', 'z', Poco::Unicode::toUpper, UTF8CyrillicToCase<false>>, NameUpperUTF8>; using FunctionUpperUTF8 = FunctionStringToString<LowerUpperUTF8Impl<'a', 'z', true>, NameUpperUTF8>;
} }
REGISTER_FUNCTION(UpperUTF8) REGISTER_FUNCTION(UpperUTF8)
{ {
factory.registerFunction<FunctionUpperUTF8>(); FunctionDocumentation::Description description
= R"(Converts a string to lowercase, assuming that the string contains valid UTF-8 encoded text. If this assumption is violated, no exception is thrown and the result is undefined.)";
FunctionDocumentation::Syntax syntax = "upperUTF8(input)";
FunctionDocumentation::Arguments arguments = {{"input", "Input with String type"}};
FunctionDocumentation::ReturnedValue returned_value = "A String data type value";
FunctionDocumentation::Examples examples = {
{"first", "SELECT upperUTF8('München') as Upperutf8;", "MÜNCHEN"},
};
FunctionDocumentation::Categories categories = {"String"};
factory.registerFunction<FunctionUpperUTF8>({description, syntax, arguments, returned_value, examples, categories});
} }
} }
#endif

View File

@ -238,7 +238,7 @@ ReadWriteBufferFromHTTP::ReadWriteBufferFromHTTP(
if (iter == http_header_entries.end()) if (iter == http_header_entries.end())
{ {
http_header_entries.emplace_back(user_agent, fmt::format("ClickHouse/{}", VERSION_STRING)); http_header_entries.emplace_back(user_agent, fmt::format("ClickHouse/{}{}", VERSION_STRING, VERSION_OFFICIAL));
} }
if (!delay_initialization && use_external_buffer) if (!delay_initialization && use_external_buffer)

View File

@ -982,10 +982,10 @@ PocoHTTPClientConfiguration ClientFactory::createClientConfiguration( // NOLINT
{ {
auto context = Context::getGlobalContextInstance(); auto context = Context::getGlobalContextInstance();
chassert(context); chassert(context);
auto proxy_configuration_resolver = DB::ProxyConfigurationResolverProvider::get(DB::ProxyConfiguration::protocolFromString(protocol), context->getConfigRef()); auto proxy_configuration_resolver = ProxyConfigurationResolverProvider::get(ProxyConfiguration::protocolFromString(protocol), context->getConfigRef());
auto per_request_configuration = [=] () { return proxy_configuration_resolver->resolve(); }; auto per_request_configuration = [=]{ return proxy_configuration_resolver->resolve(); };
auto error_report = [=] (const DB::ProxyConfiguration & req) { proxy_configuration_resolver->errorReport(req); }; auto error_report = [=](const ProxyConfiguration & req) { proxy_configuration_resolver->errorReport(req); };
auto config = PocoHTTPClientConfiguration( auto config = PocoHTTPClientConfiguration(
per_request_configuration, per_request_configuration,

View File

@ -1,4 +1,5 @@
#include <Poco/Timespan.h> #include <Poco/Timespan.h>
#include <Common/config_version.h>
#include "config.h" #include "config.h"
#if USE_AWS_S3 #if USE_AWS_S3
@ -17,6 +18,7 @@
#include <IO/WriteBufferFromString.h> #include <IO/WriteBufferFromString.h>
#include <IO/Operators.h> #include <IO/Operators.h>
#include <IO/S3/ProviderType.h> #include <IO/S3/ProviderType.h>
#include <Interpreters/Context.h>
#include <aws/core/http/HttpRequest.h> #include <aws/core/http/HttpRequest.h>
#include <aws/core/http/HttpResponse.h> #include <aws/core/http/HttpResponse.h>
@ -29,6 +31,7 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
static const int SUCCESS_RESPONSE_MIN = 200; static const int SUCCESS_RESPONSE_MIN = 200;
static const int SUCCESS_RESPONSE_MAX = 299; static const int SUCCESS_RESPONSE_MAX = 299;
@ -84,7 +87,7 @@ namespace DB::S3
{ {
PocoHTTPClientConfiguration::PocoHTTPClientConfiguration( PocoHTTPClientConfiguration::PocoHTTPClientConfiguration(
std::function<DB::ProxyConfiguration()> per_request_configuration_, std::function<ProxyConfiguration()> per_request_configuration_,
const String & force_region_, const String & force_region_,
const RemoteHostFilter & remote_host_filter_, const RemoteHostFilter & remote_host_filter_,
unsigned int s3_max_redirects_, unsigned int s3_max_redirects_,
@ -94,7 +97,7 @@ PocoHTTPClientConfiguration::PocoHTTPClientConfiguration(
bool s3_use_adaptive_timeouts_, bool s3_use_adaptive_timeouts_,
const ThrottlerPtr & get_request_throttler_, const ThrottlerPtr & get_request_throttler_,
const ThrottlerPtr & put_request_throttler_, const ThrottlerPtr & put_request_throttler_,
std::function<void(const DB::ProxyConfiguration &)> error_report_) std::function<void(const ProxyConfiguration &)> error_report_)
: per_request_configuration(per_request_configuration_) : per_request_configuration(per_request_configuration_)
, force_region(force_region_) , force_region(force_region_)
, remote_host_filter(remote_host_filter_) , remote_host_filter(remote_host_filter_)
@ -107,6 +110,8 @@ PocoHTTPClientConfiguration::PocoHTTPClientConfiguration(
, s3_use_adaptive_timeouts(s3_use_adaptive_timeouts_) , s3_use_adaptive_timeouts(s3_use_adaptive_timeouts_)
, error_report(error_report_) , error_report(error_report_)
{ {
/// This is used to identify configurations created by us.
userAgent = std::string(VERSION_FULL) + VERSION_OFFICIAL;
} }
void PocoHTTPClientConfiguration::updateSchemeAndRegion() void PocoHTTPClientConfiguration::updateSchemeAndRegion()
@ -166,6 +171,17 @@ PocoHTTPClient::PocoHTTPClient(const PocoHTTPClientConfiguration & client_config
{ {
} }
PocoHTTPClient::PocoHTTPClient(const Aws::Client::ClientConfiguration & client_configuration)
: timeouts(ConnectionTimeouts()
.withConnectionTimeout(Poco::Timespan(client_configuration.connectTimeoutMs * 1000))
.withSendTimeout(Poco::Timespan(client_configuration.requestTimeoutMs * 1000))
.withReceiveTimeout(Poco::Timespan(client_configuration.requestTimeoutMs * 1000))
.withTCPKeepAliveTimeout(Poco::Timespan(
client_configuration.enableTcpKeepAlive ? client_configuration.tcpKeepAliveIntervalMs * 1000 : 0))),
remote_host_filter(Context::getGlobalContextInstance()->getRemoteHostFilter())
{
}
std::shared_ptr<Aws::Http::HttpResponse> PocoHTTPClient::MakeRequest( std::shared_ptr<Aws::Http::HttpResponse> PocoHTTPClient::MakeRequest(
const std::shared_ptr<Aws::Http::HttpRequest> & request, const std::shared_ptr<Aws::Http::HttpRequest> & request,
Aws::Utils::RateLimits::RateLimiterInterface * readLimiter, Aws::Utils::RateLimits::RateLimiterInterface * readLimiter,
@ -381,8 +397,11 @@ void PocoHTTPClient::makeRequestInternalImpl(
try try
{ {
const auto proxy_configuration = per_request_configuration(); ProxyConfiguration proxy_configuration;
for (unsigned int attempt = 0; attempt <= s3_max_redirects; ++attempt) if (per_request_configuration)
proxy_configuration = per_request_configuration();
for (size_t attempt = 0; attempt <= s3_max_redirects; ++attempt)
{ {
Poco::URI target_uri(uri); Poco::URI target_uri(uri);
@ -500,7 +519,6 @@ void PocoHTTPClient::makeRequestInternalImpl(
LOG_TEST(log, "Redirecting request to new location: {}", location); LOG_TEST(log, "Redirecting request to new location: {}", location);
addMetric(request, S3MetricType::Redirects); addMetric(request, S3MetricType::Redirects);
continue; continue;
} }
@ -548,9 +566,9 @@ void PocoHTTPClient::makeRequestInternalImpl(
} }
else else
{ {
if (status_code == 429 || status_code == 503) if (status_code == 429 || status_code == 503)
{ // API throttling {
/// API throttling
addMetric(request, S3MetricType::Throttling); addMetric(request, S3MetricType::Throttling);
} }
else if (status_code >= 300) else if (status_code >= 300)

View File

@ -20,6 +20,7 @@
#include <aws/core/http/HttpRequest.h> #include <aws/core/http/HttpRequest.h>
#include <aws/core/http/standard/StandardHttpResponse.h> #include <aws/core/http/standard/StandardHttpResponse.h>
namespace Aws::Http::Standard namespace Aws::Http::Standard
{ {
class StandardHttpResponse; class StandardHttpResponse;
@ -27,18 +28,20 @@ class StandardHttpResponse;
namespace DB namespace DB
{ {
class Context; class Context;
} }
namespace DB::S3 namespace DB::S3
{ {
class ClientFactory; class ClientFactory;
class PocoHTTPClient; class PocoHTTPClient;
struct PocoHTTPClientConfiguration : public Aws::Client::ClientConfiguration struct PocoHTTPClientConfiguration : public Aws::Client::ClientConfiguration
{ {
std::function<DB::ProxyConfiguration()> per_request_configuration; std::function<ProxyConfiguration()> per_request_configuration;
String force_region; String force_region;
const RemoteHostFilter & remote_host_filter; const RemoteHostFilter & remote_host_filter;
unsigned int s3_max_redirects; unsigned int s3_max_redirects;
@ -54,13 +57,13 @@ struct PocoHTTPClientConfiguration : public Aws::Client::ClientConfiguration
size_t http_keep_alive_timeout = DEFAULT_HTTP_KEEP_ALIVE_TIMEOUT; size_t http_keep_alive_timeout = DEFAULT_HTTP_KEEP_ALIVE_TIMEOUT;
size_t http_keep_alive_max_requests = DEFAULT_HTTP_KEEP_ALIVE_MAX_REQUEST; size_t http_keep_alive_max_requests = DEFAULT_HTTP_KEEP_ALIVE_MAX_REQUEST;
std::function<void(const DB::ProxyConfiguration &)> error_report; std::function<void(const ProxyConfiguration &)> error_report;
void updateSchemeAndRegion(); void updateSchemeAndRegion();
private: private:
PocoHTTPClientConfiguration( PocoHTTPClientConfiguration(
std::function<DB::ProxyConfiguration()> per_request_configuration_, std::function<ProxyConfiguration()> per_request_configuration_,
const String & force_region_, const String & force_region_,
const RemoteHostFilter & remote_host_filter_, const RemoteHostFilter & remote_host_filter_,
unsigned int s3_max_redirects_, unsigned int s3_max_redirects_,
@ -70,13 +73,13 @@ private:
bool s3_use_adaptive_timeouts_, bool s3_use_adaptive_timeouts_,
const ThrottlerPtr & get_request_throttler_, const ThrottlerPtr & get_request_throttler_,
const ThrottlerPtr & put_request_throttler_, const ThrottlerPtr & put_request_throttler_,
std::function<void(const DB::ProxyConfiguration &)> error_report_ std::function<void(const ProxyConfiguration &)> error_report_);
);
/// Constructor of Aws::Client::ClientConfiguration must be called after AWS SDK initialization. /// Constructor of Aws::Client::ClientConfiguration must be called after AWS SDK initialization.
friend ClientFactory; friend ClientFactory;
}; };
class PocoHTTPResponse : public Aws::Http::Standard::StandardHttpResponse class PocoHTTPResponse : public Aws::Http::Standard::StandardHttpResponse
{ {
public: public:
@ -116,10 +119,12 @@ private:
Aws::Utils::Stream::ResponseStream body_stream; Aws::Utils::Stream::ResponseStream body_stream;
}; };
class PocoHTTPClient : public Aws::Http::HttpClient class PocoHTTPClient : public Aws::Http::HttpClient
{ {
public: public:
explicit PocoHTTPClient(const PocoHTTPClientConfiguration & client_configuration); explicit PocoHTTPClient(const PocoHTTPClientConfiguration & client_configuration);
explicit PocoHTTPClient(const Aws::Client::ClientConfiguration & client_configuration);
~PocoHTTPClient() override = default; ~PocoHTTPClient() override = default;
std::shared_ptr<Aws::Http::HttpResponse> MakeRequest( std::shared_ptr<Aws::Http::HttpResponse> MakeRequest(
@ -166,14 +171,14 @@ protected:
static S3MetricKind getMetricKind(const Aws::Http::HttpRequest & request); static S3MetricKind getMetricKind(const Aws::Http::HttpRequest & request);
void addMetric(const Aws::Http::HttpRequest & request, S3MetricType type, ProfileEvents::Count amount = 1) const; void addMetric(const Aws::Http::HttpRequest & request, S3MetricType type, ProfileEvents::Count amount = 1) const;
std::function<DB::ProxyConfiguration()> per_request_configuration; std::function<ProxyConfiguration()> per_request_configuration;
std::function<void(const DB::ProxyConfiguration &)> error_report; std::function<void(const ProxyConfiguration &)> error_report;
ConnectionTimeouts timeouts; ConnectionTimeouts timeouts;
const RemoteHostFilter & remote_host_filter; const RemoteHostFilter & remote_host_filter;
unsigned int s3_max_redirects; unsigned int s3_max_redirects = 0;
bool s3_use_adaptive_timeouts = true; bool s3_use_adaptive_timeouts = true;
bool enable_s3_requests_logging; bool enable_s3_requests_logging = false;
bool for_disk_s3; bool for_disk_s3 = false;
/// Limits get request per second rate for GET, SELECT and all other requests, excluding throttled by put throttler /// Limits get request per second rate for GET, SELECT and all other requests, excluding throttled by put throttler
/// (i.e. throttles GetObject, HeadObject) /// (i.e. throttles GetObject, HeadObject)

View File

@ -15,7 +15,10 @@ namespace DB::S3
std::shared_ptr<Aws::Http::HttpClient> std::shared_ptr<Aws::Http::HttpClient>
PocoHTTPClientFactory::CreateHttpClient(const Aws::Client::ClientConfiguration & client_configuration) const PocoHTTPClientFactory::CreateHttpClient(const Aws::Client::ClientConfiguration & client_configuration) const
{ {
return std::make_shared<PocoHTTPClient>(static_cast<const PocoHTTPClientConfiguration &>(client_configuration)); if (client_configuration.userAgent.starts_with("ClickHouse"))
return std::make_shared<PocoHTTPClient>(static_cast<const PocoHTTPClientConfiguration &>(client_configuration));
else /// This client is created inside the AWS SDK with default settings to obtain ECS credentials from localhost.
return std::make_shared<PocoHTTPClient>(client_configuration);
} }
std::shared_ptr<Aws::Http::HttpRequest> PocoHTTPClientFactory::CreateHttpRequest( std::shared_ptr<Aws::Http::HttpRequest> PocoHTTPClientFactory::CreateHttpRequest(

View File

@ -11,11 +11,15 @@
#include <Interpreters/Cache/EvictionCandidates.h> #include <Interpreters/Cache/EvictionCandidates.h>
#include <Interpreters/Context.h> #include <Interpreters/Context.h>
#include <base/hex.h> #include <base/hex.h>
#include <Common/callOnce.h>
#include <Common/Exception.h>
#include <Common/ThreadPool.h> #include <Common/ThreadPool.h>
#include <Common/ElapsedTimeProfileEventIncrement.h> #include <Common/ElapsedTimeProfileEventIncrement.h>
#include <Core/ServerUUID.h> #include <Core/ServerUUID.h>
#include <exception>
#include <filesystem> #include <filesystem>
#include <mutex>
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -88,6 +92,7 @@ FileCache::FileCache(const std::string & cache_name, const FileCacheSettings & s
, bypass_cache_threshold(settings.enable_bypass_cache_with_threshold ? settings.bypass_cache_threshold : 0) , bypass_cache_threshold(settings.enable_bypass_cache_with_threshold ? settings.bypass_cache_threshold : 0)
, boundary_alignment(settings.boundary_alignment) , boundary_alignment(settings.boundary_alignment)
, load_metadata_threads(settings.load_metadata_threads) , load_metadata_threads(settings.load_metadata_threads)
, load_metadata_asynchronously(settings.load_metadata_asynchronously)
, write_cache_per_user_directory(settings.write_cache_per_user_id_directory) , write_cache_per_user_directory(settings.write_cache_per_user_id_directory)
, keep_current_size_to_max_ratio(1 - settings.keep_free_space_size_ratio) , keep_current_size_to_max_ratio(1 - settings.keep_free_space_size_ratio)
, keep_current_elements_to_max_ratio(1 - settings.keep_free_space_elements_ratio) , keep_current_elements_to_max_ratio(1 - settings.keep_free_space_elements_ratio)
@ -136,7 +141,17 @@ const FileCache::UserInfo & FileCache::getInternalUser()
bool FileCache::isInitialized() const bool FileCache::isInitialized() const
{ {
return is_initialized.load(std::memory_order_seq_cst); return is_initialized;
}
void FileCache::throwInitExceptionIfNeeded()
{
if (load_metadata_asynchronously)
return;
std::lock_guard lock(init_mutex);
if (init_exception)
std::rethrow_exception(init_exception);
} }
const String & FileCache::getBasePath() const const String & FileCache::getBasePath() const
@ -170,6 +185,35 @@ void FileCache::assertInitialized() const
} }
void FileCache::initialize() void FileCache::initialize()
{
// Prevent initialize() from running twice. This may be caused by two cache disks being created with the same path (see integration/test_filesystem_cache).
callOnce(initialize_called, [&] {
bool need_to_load_metadata = fs::exists(getBasePath());
try
{
if (!need_to_load_metadata)
fs::create_directories(getBasePath());
status_file = make_unique<StatusFile>(fs::path(getBasePath()) / "status", StatusFile::write_full_info);
}
catch (...)
{
init_exception = std::current_exception();
tryLogCurrentException(__PRETTY_FUNCTION__);
throw;
}
if (load_metadata_asynchronously)
{
load_metadata_main_thread = ThreadFromGlobalPool([this, need_to_load_metadata] { initializeImpl(need_to_load_metadata); });
}
else
{
initializeImpl(need_to_load_metadata);
}
});
}
void FileCache::initializeImpl(bool load_metadata)
{ {
std::lock_guard lock(init_mutex); std::lock_guard lock(init_mutex);
@ -178,16 +222,10 @@ void FileCache::initialize()
try try
{ {
if (fs::exists(getBasePath())) if (load_metadata)
{
loadMetadata(); loadMetadata();
}
else
{
fs::create_directories(getBasePath());
}
status_file = make_unique<StatusFile>(fs::path(getBasePath()) / "status", StatusFile::write_full_info); metadata.startup();
} }
catch (...) catch (...)
{ {
@ -196,8 +234,6 @@ void FileCache::initialize()
throw; throw;
} }
metadata.startup();
if (keep_current_size_to_max_ratio != 1 || keep_current_elements_to_max_ratio != 1) if (keep_current_size_to_max_ratio != 1 || keep_current_elements_to_max_ratio != 1)
{ {
keep_up_free_space_ratio_task = Context::getGlobalContextInstance()->getSchedulePool().createTask(log->name(), [this] { freeSpaceRatioKeepingThreadFunc(); }); keep_up_free_space_ratio_task = Context::getGlobalContextInstance()->getSchedulePool().createTask(log->name(), [this] { freeSpaceRatioKeepingThreadFunc(); });
@ -205,6 +241,7 @@ void FileCache::initialize()
} }
is_initialized = true; is_initialized = true;
LOG_TEST(log, "Initialized cache from {}", metadata.getBaseDirectory());
} }
CachePriorityGuard::Lock FileCache::lockCache() const CachePriorityGuard::Lock FileCache::lockCache() const
@ -1197,7 +1234,6 @@ void FileCache::loadMetadataImpl()
std::vector<ThreadFromGlobalPool> loading_threads; std::vector<ThreadFromGlobalPool> loading_threads;
std::exception_ptr first_exception; std::exception_ptr first_exception;
std::mutex set_exception_mutex; std::mutex set_exception_mutex;
std::atomic<bool> stop_loading = false;
LOG_INFO(log, "Loading filesystem cache with {} threads from {}", load_metadata_threads, metadata.getBaseDirectory()); LOG_INFO(log, "Loading filesystem cache with {} threads from {}", load_metadata_threads, metadata.getBaseDirectory());
@ -1207,7 +1243,7 @@ void FileCache::loadMetadataImpl()
{ {
loading_threads.emplace_back([&] loading_threads.emplace_back([&]
{ {
while (!stop_loading) while (!stop_loading_metadata)
{ {
try try
{ {
@ -1224,7 +1260,7 @@ void FileCache::loadMetadataImpl()
if (!first_exception) if (!first_exception)
first_exception = std::current_exception(); first_exception = std::current_exception();
} }
stop_loading = true; stop_loading_metadata = true;
return; return;
} }
} }
@ -1237,7 +1273,7 @@ void FileCache::loadMetadataImpl()
if (!first_exception) if (!first_exception)
first_exception = std::current_exception(); first_exception = std::current_exception();
} }
stop_loading = true; stop_loading_metadata = true;
break; break;
} }
} }
@ -1424,6 +1460,11 @@ FileCache::~FileCache()
void FileCache::deactivateBackgroundOperations() void FileCache::deactivateBackgroundOperations()
{ {
shutdown.store(true); shutdown.store(true);
stop_loading_metadata = true;
if (load_metadata_main_thread.joinable())
load_metadata_main_thread.join();
metadata.shutdown(); metadata.shutdown();
if (keep_up_free_space_ratio_task) if (keep_up_free_space_ratio_task)
keep_up_free_space_ratio_task->deactivate(); keep_up_free_space_ratio_task->deactivate();

View File

@ -8,6 +8,7 @@
#include <IO/ReadSettings.h> #include <IO/ReadSettings.h>
#include <Common/callOnce.h>
#include <Common/ThreadPool.h> #include <Common/ThreadPool.h>
#include <Common/StatusFile.h> #include <Common/StatusFile.h>
#include <Interpreters/Cache/LRUFileCachePriority.h> #include <Interpreters/Cache/LRUFileCachePriority.h>
@ -82,6 +83,9 @@ public:
bool isInitialized() const; bool isInitialized() const;
/// Throws if `!load_metadata_asynchronously` and there is an exception in `init_exception`
void throwInitExceptionIfNeeded();
const String & getBasePath() const; const String & getBasePath() const;
static Key createKeyForPath(const String & path); static Key createKeyForPath(const String & path);
@ -199,6 +203,9 @@ private:
const size_t bypass_cache_threshold; const size_t bypass_cache_threshold;
const size_t boundary_alignment; const size_t boundary_alignment;
size_t load_metadata_threads; size_t load_metadata_threads;
const bool load_metadata_asynchronously;
std::atomic<bool> stop_loading_metadata = false;
ThreadFromGlobalPool load_metadata_main_thread;
const bool write_cache_per_user_directory; const bool write_cache_per_user_directory;
BackgroundSchedulePool::TaskHolder keep_up_free_space_ratio_task; BackgroundSchedulePool::TaskHolder keep_up_free_space_ratio_task;
@ -210,6 +217,7 @@ private:
std::exception_ptr init_exception; std::exception_ptr init_exception;
std::atomic<bool> is_initialized = false; std::atomic<bool> is_initialized = false;
OnceFlag initialize_called;
mutable std::mutex init_mutex; mutable std::mutex init_mutex;
std::unique_ptr<StatusFile> status_file; std::unique_ptr<StatusFile> status_file;
std::atomic<bool> shutdown = false; std::atomic<bool> shutdown = false;
@ -247,6 +255,8 @@ private:
*/ */
FileCacheQueryLimitPtr query_limit; FileCacheQueryLimitPtr query_limit;
void initializeImpl(bool load_metadata);
void assertInitialized() const; void assertInitialized() const;
void assertCacheCorrectness(); void assertCacheCorrectness();

Some files were not shown because too many files have changed in this diff Show More